home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-07-30 | 58.2 KB | 2,272 lines |
-
- ; KISS TNC FOR THE TNC-2 AND CLONES
- ;
- ; K3MC 30 SEP 86 - ORIGINAL VERSION
- ;
- ; 1 MAR 87. FIXED ALL KNOWN BUGS. RE-ARRANGE CODE TO ALLOW ROMING (THIS
- ; MEANS THAT DATA AREAS NEED TO BE INITIALIZED FROM THE CODE). FIGURE OUT THE
- ; STACK POINTER GIVEN THE AMOUNT OF AVAILABLE RAM. INCLUDE THE CODES 05 00
- ; AND 05 01 TO MEAN FULL DUPLEX OFF AND FULL DUPLEX ON, RESPECTIVELY.
- ; CLEAR OUT ALL AVAILABLE RAM. DO A "DANCE" WITH LEDS WHEN INITIALLY BOOTED:
- ; FLASH THE LED(S) FOR ABOUT 5 SECONDS SUCH THAT CON ONLY FLASHES IF YOU HAVE
- ; 8K RAM, STA ONLY FLASHES IF 16K RAM, AND STA AND CON FLASH IF 32K RAM.
- ;
- ; 29 MAR 87. ADD CODE TO DISCARD BREAK CHARS, AND CHARS WITH FRAMING ERRORS.
- ; FIX BUG IN IB_RCA WHICH DID NOT DISCARD NULL RECEIVED FRAMES.
-
- ; Modified by John Wiseman, G8BPQ for use with ZILOG assembler,
- ; and to reset on error conditions (underrun or buffer overload)
- ;
- ; CWID added - june 1990
- ;
- ; AUGUST 90 - FIX FOR 'FLAKY DCD' PROBLEM - IF DCD DROPS DURING A FRAME,
- ; THEN THE FIRST PART IS JUNKED, AND THE REST TREATED AS A VALID FRAME
- ;
- ;PROM EQU 0 ; DOWN LINE LOAD
- PROM EQU 1 ; PROM VERSION
-
-
- COND PROM-1
- ORG 8000H ; FOR DOWN LINE LOAD
- ENDC
-
-
-
- FALSE EQU 0
- TRUE EQU 0FFH
-
-
- I_REGISTER EQU $/256
-
- SIO EQU 0DCH ;ACTUALLY, ONLY A5 IS USED FOR SIO -CS
-
- A_DAT EQU SIO+0 ;MODEM PORT
- A_CTL EQU SIO+1 ;MODEM PORT
-
- B_DAT EQU SIO+2 ;USER SERIAL PORT
- B_CTL EQU SIO+3 ;USER SERIAL PORT
-
- DCD EQU 8 ;BIT IN RR0, USED IN CH A
-
- TBE EQU 4 ;TX BUFFER EMPTY BIT
- RTS EQU 2 ;REQUEST TO SEND (PTT BIT IN WR5 OF CHAN A)
- FRAMING_ERROR EQU 40H ;BIT IN RR1 FOR ASYNC FRAMING ERROR
- BREAK_ABORT EQU 80H ;BIT IN RR0 FOR ASYNC BREAK DETECTION
-
- FEND EQU 300O ;300 OCTAL
- FESC EQU 333O ;333 OCTAL
- TFEND EQU 334O ;334 OCTAL
- TFESC EQU 335O ;335 OCTAL
-
- ALEDON EQU 69H ;BITS FOR WR5 TO TURN ON STA LED
- ALEDOFF EQU 0E9H ;BITS FOR WR5 TO TURN OFF STA LED
-
- ALED EQU 80H ;THE DTR BIT IN CH A WR5, WE WILL SOON REMOVE
- ;PREVIOUS 2 DEFINITIONS & USE THE MEMORY LOC.
- ;A_WR5 TO HOLD CH A WR5'S VALUE, BECAUSE WE
- ;NEED TO BE AWARE WHEN WE ARE TRANSMITTING!
-
- BLEDON EQU 6AH ;BITS FOR WR5 TO TURN ON CON LED
- BLEDOFF EQU 0EAH ;BITS FOR WR5 TO TURN OFF CON LED
- BLED EQU 80H
-
- N_EVENTS EQU 4 ; SO FAR, ONLY 3 REAL-TIME EVENTS
- ; + CLOCK FOR CWID
-
- START:
- JP CODE_START ;GO AROUND THIS DATA AREA
- VERSION:
- DEFM 'G8BPQ 16SEP90' ;13 BYTES (EXACTLY!) HERE FOR VERSION STRING
-
- DEFW IB_TBE ;CH B TRANSMITTER BUFFER EMPTY INTERRUPT/USER
- DEFW IB_EXT ;CH B EXT/STATUS CHANGE/USER
- DEFW IB_RCA ;CH B RECEIVED CHAR AVAILABLE/USER
- DEFW IB_SPECIAL ;CH B SPECIAL RECEIVE CONDITION/USER
-
- DEFW IA_TBE ;CH A TRANSMITTER BUFFER EMPTY INTERRUPT/MODEM
- DEFW IA_EXT ;CH A EXT/STATUS CHANGE/MODEM
- DEFW IA_RCA ;CH A RECEIVED CHAR AVAILABLE/MODEM
- DEFW IA_SPECIAL ;CH A SPECIAL RECEIVE CONDITION/MODEM
-
- CHANNEL DEFB 0 ; DUMMY FOR JKISSP
-
- CWID DEFS 512 ; PATCH ID IN HERE - 20 BYTES PER SECOND,
- ; SO ENOUGH ROOM FOR 25 SECS OF ID!
-
- ;
- A_INIT:
- DEFB 18H,4,20H,1,1BH,7,7EH,5,0E9H,3,0C9H ;FOR MODEM
- A_SIZE EQU $-A_INIT
-
- B_INIT:
- DEFB 18H,4,44H,2,10H,3,0C1H,5,0EAH,1,1FH ;FOR TTY
- B_SIZE EQU $-B_INIT
-
-
- ;THIS IS THE DATA AREA WHICH GETS BLASTED INTO RAM UPON STARTUP:
- DATA_INIT:
-
- ;NBUFFERS:
- DEFB 0 ;UP TO 255 BUFFERS
- ;FREE:
- DEFW 0 ;ADDRESS OF 1ST BUFFER ON FREE LIST
-
- ;RX_BUF:
- DEFW 0 ;ADDRESS OF CURRENT RECEIVE BUFFER
- ;RX_HEAD:
- DEFW 0 ;ADDRESS OF 1ST RX BUFFER
- ;RX_ALLOCATED_BUFFER:
- DEFB 0 ;SET NON-ZERO IF WE'RE IN RX STATE
-
- ;RX_FLUSHING:
- DEFB 0 ;IS NON-0 IF WE RAN OUT OF BUFFER
- ;SPACE AND ARE CURRENTLY FLUSHING THIS
- ;FRAME BEING RECEIVED. USED BY
- ;IA_RCA AND RESET BY IA_EXT.
-
-
- ;IN_BUFFER:
- DEFW 0 ;ADDR OF CURRENT INPUT BUFFER
- ;IN_HEAD:
- DEFW 0 ;ADDR OF 1ST INPUT BUFFER
- ;IN_ALLOCATED_BUFFER:
- DEFB 0 ;IS NOT 0 IF WE'VE ALREADY ALLOC'D BUF
-
- ;IN_STATE:
- DEFB 1 ;CONVERT BACK TO 1 IN V.32 CODE
-
- ;INPUT STATE MACHINE STATE
- ;4 MAR 8: MAKE IT 0 (FROM 1) BECUZ
- ;NOISE ON LINE IS FIRST TRIGGERING THE
- ;CODE TO ASSUME THAT A FRAME IS COMING
- ;FROM THE HOST..... COMMENT BELOW WAS
- ;APPROPRIATE BEFORE
- ;ASSUME THAT WE'VE SEEN AN FEND FROM
- ;(NON-EXISTENT) "PREVIOUS" FRAME. THIS
- ;MEANS THAT WHEN WE ARE RECEIVING DATA
- ;FROM USER, THERE NEED BE ONLY THE
- ;FEND CHAR AT THE END OF A FRAME, AND
- ;NOT AT THE BEGINNING (ALTHOUGH IF A
- ;FEND IS AT THE BEGINNING, IT IS
- ;IGNORED.)
-
- ;OUT_STARTED:
- DEFB 0 ;OUTPUT NOT STARTED YET (LOGICAL VAR)
- ;OUT_HEAD_CBUF:
- DEFW OUT_TOP ;ADDRESS OF BUFFER TO BE OUTPUT RS232
- ;OUT_TAIL_CBUF:
- DEFW OUT_TOP ;POINTER TO NEXT FREE OUTPUT BUFFER
- ;OUT_CHAIN_HEAD:
- DEFW 0 ;ADDR OF BUFFER WE ARE NOW OUTPUTTING
-
- ;TX_STARTED:
- DEFB 0 ;NON-ZERO IF WE'VE BEGUN TXING CHARS
- ;TX_HEAD_CBUF:
- DEFW TX_TOP ;CURRENT ACTIVE CBUF ENTRY (IF ACTIVE)
- ;TX_TAIL_CBUF:
- DEFW TX_TOP ;NEXT FREE CBUF ENTRY
-
- ;TX_CHAIN_HEAD:
- DEFW 0 ;HOLDS ADDRESS OF THE CURRENT BUFFER
- ;CHAIN HEAD THAT WE ARE TRANSMITTING
- ;TX_OUTSTANDING:
- DEFB 0 ;NUMBER OF TX CBUFS QUEUED UP FOR TX
-
- ;DCD_STATE:
- DEFB 0 ;IS NON 0 IF DCD LED IS ON
-
- ;THESE NEXT TWO ARE USED BY THE IB_TBE INTERRUPT ROUTINE.
- ;IB_ESC_MODE:
- DEFB 0 ; NOT IN ESCAPED MODE
- ;IB_CHAR:
- DEFS 1 ; NEXT CHAR TO SEND IF ESCAPED MODE
- ;IN_BREAK:
- DEFB 0 ; NON-ZERO IF WE ARE IN A BREAK DETECT
- ; SEQUENCE ON THE ASYNC PORT
- ;FULL_DUPLEX:
- DEFB 0 ;NOT FULL DUPLEX TO START
- ;A_WR5:
- DEFB ALEDOFF ;STATE OF STA LED & RTS (PTT) LINE,
- ;MAINLY... (FOR CH A ONLY [MODEM] )
- ;B_WR5:
- DEFB BLEDOFF
-
- DATA_SIZE EQU $-DATA_INIT
-
- ;***************************************************************************
- CODE_START:
- DI ;NO INTERRUPTS FOR THE MOMENT...
-
- ;INIT SIO. THIS IS REQUIRED EVEN IF WE WANNA FLASH LEDS...
-
- IN A,(A_CTL) ;ASSURE WE ARE TALKING TO CH 0
- LD C,A_CTL
- LD B,A_SIZE
- LD HL,A_INIT
- OTIR ;INIT SYNC (MODEM) PORT
-
- ;INIT ASYNC PORT, ALSO TO ALLOW FLASHING LEDS
-
- IN A,(B_CTL) ;ASSURE WE ARE TALKING TO CH 0
- LD C,B_CTL
- LD B,B_SIZE
- LD HL,B_INIT
- OTIR ;INIT ASYNC PORT & INTERRUPT VECTOR
-
- ;
- ; FIGURE OUT WHERE TOP OF STACK IS, SET STACK POINTER.
- ; SILLY TNC-2 DOES NOT DO COMPLETE ADDRESS DECODING FOR THE RAMS IF YOU ARE
- ; USING ONLY THE TWO 8K X 8 CHIPS. HACK TO FIGURE OUT TOP OF MEMORY SO WE CAN
- ; SET STACK POINTER. NEWER HACK TO SEE IF WE'VE ONLY GOT 8K RAM.
-
- LD A,(9FFFH) ;TOP OF RAM IF ONLY 8K
- CPL
- LD B,A
- LD (9FFFH),A ;WRITE ONE'S COMPLEMENT INTO MEM
-
- LD A,(9FFFH)
- CP B ;SEE IF IT "TOOK"
- JP Z,OK_8 ;YES, WE HAVE AT LEAST 8K OF RAM
-
-
- HALT ;ELSE THERE IS NO RAM, SO STOP
-
- OK_8:
- LD A,(0BFFFH) ;TOP OF RAM IF 16K
- CPL
- LD B,A
- LD (0BFFFH),A ;SAME ONE'S COMPLEMENT HACK
-
- LD A,(0BFFFH)
- CP B
- JP Z,OK_16 ;WE HAVE AT LEAST 16K OF RAM
-
- LD SP,0A000H
- LD D,0FFH ;BLINK CON LED
- LD E,0 ;BUT NOT STA LED (I.E., WE HAVE 8K)
- JP STACK_LOADED ;ELSE WE ONLY HAVE 8K OF RAM
- ;BECAUSE PREVIOUS COMPARE FAILED
-
- ;HERE IF WE'VE GOT AT LEAST 16K RAM
- OK_16:
- LD A,55H ;ONE VALUE
- LD (0BFFFH),A
- LD A,0AAH
- LD (0FFFFH),A ;OTHER VALUE
-
- LD A,(0BFFFH) ;GET WHAT SHOULD BE 55H IF 32K
-
- CP 55H
- LD SP,0
- LD DE,0FFFFH ;BLINK BOTH CON AND STA LEDS (IF 32K)
- JR Z,STACK_LOADED ;IF IS 55H, THEN WE'VE GOT 32 K, ELSE 16 K
-
- LD SP,0C000H ;FORCE STACK VALUE.
- LD D,0 ;DO NOT BLINK CON LED IF 16K RAM
-
- STACK_LOADED:
- PUSH DE ;DE HAS LOGICAL VALUES WHICH TELL US WHICH
- ;LEDS TO FLASH (WHICH WE DO LATER...)
- EXX
- POP HL ;TEMP. STORE THIS INFO IN OTHER REG SET
- EXX
-
-
- ;CLEAR OUT RAM.
-
- LD HL,0
- ADD HL,SP ;NOW HL HAS VALUE OF SP (THAT IS, TOP OF
- ;MEMORY + 1)
- DEC HL ;NOW HL HAS TOP OF MEMORY ADDRESS
- LD DE,FREE_RAM ;GET START OF AVAILABLE FREE RAM
- XOR A ;CLEAR CARRY AND SET A TO 0
- LD (DE),A ;FIRST FREE RAM LOCATION IS ZEROED....
- SBC HL,DE ;GET INTO HL # OF BYTES OF FREE RAM. IF WE
- ;ARE IN ROM, THEN ALL RAM IS FREE, ELSE IF WE
- ;ARE RUNNING FROM RAM, THE CODE PART IS NOT
- ;FREE, AND THIS COMPENSATES FOR THIS.
-
- DEC HL ;ONE FEWER BYTES FOR NUMBER TO MOVE...
- LD B,H
- LD C,L ;GET BYTE COUNT INTO BC
-
- LD H,D
- LD L,E ;GET "SOURCE" ADDRESS = FREE_RAM
-
- INC DE ;SET "DESTINATION" ADDRESS = FREE_RAM + 1
-
- LDIR ;ZERO MEMORY.
-
- ;THIS SEQUENCE LOADS UP OUR DATA AREA IN RAM:
-
- LD HL,DATA_INIT
- LD DE,NBUFFERS
- LD BC,DATA_SIZE
- LDIR
-
-
- ; SET STACK SIZE AND INIT FREE BUFFER LIST.
-
- LD HL,0
- ADD HL,SP ;GET VALUE OF SP, HIGH MEMORY
- LD DE,100 ;50 WORDS FOR STACK
- OR A ;CLEAR CARRY
- SBC HL,DE ;NOW HL HAS "PSEUDO TOP OF MEMORY"
- LD DE,BOTTOM ;"PSEUDO BOTTOM OF MEMORY"
- OR A
- SBC HL,DE ;HL NOW HAS SIZE OF AVAILABLE MEMORY
- RL L ;PUT MSB INTO CARRY
- RL H ;PUT CARRY INTO LSB
- ;NOW H HAS NUMBER OF BUFFERS AVAILABLE
- LD A,H
- LD (NBUFFERS),A ;SAVE THIS NUMBER IN MEMORY
-
- LD HL,BOTTOM ;BEGINNING OF BUFFER SPACE
- LD (FREE),HL ;NOW IT'S ALSO TOP OF FREE LIST
- ; INIT BUFFER FREE LIST
- LD B,A ;GET NBUFFERS (SEE ABOVE)
- DEC B ;BECAUSE LAST ONE HAS 0 AS "NEXT"
- IBLOOP:
- PUSH HL
- LD DE,128
- ADD HL,DE ;HL HAS "NEXT" POINTER
- EX DE,HL ;DE HAS "NEXT" POINTER
- POP HL ;HL NOW HAS POINTER TO CURRENT BUFFER
-
- LD (HL),E ;LOW BYTE OF "NEXT" POINTER FIRST
- INC HL
- LD (HL),D ;NOW HI BYTE
- INC HL
- XOR A
- LD (HL),A ;ZERO OUT COUNT FIELD
- INC HL
- LD (HL),A ;ZERO OUT # OF BYTES READ FIELD
-
- EX DE,HL ;HL IS NOW POINTER TO NEXT BUFFER
- DJNZ IBLOOP ;AND INIT ALL THE AVAILABLE BUFFERS
-
- XOR A
- LD (HL),A ;LAST "NEXT" ADDRESS IS 0
- INC HL
- LD (HL),A ;DITTO
-
- INC HL
- LD (HL),A ;ZERO OUT COUNT FIELD
- INC HL
- LD (HL),A ;ZERO OUT # OF BYTES READ FIELD
-
- ;INIT REGS FOR IB_EXT INTERRUPT
- EXX
- LD BC,0 ;SET PREV STATE OF SYNC PIN,FOR 1200HZ
- LD DE,0 ;COUNT OF # OF INTERRUPTS INIT
- EXX
-
- XOR A
- LD (RX_ALLOCATED_BUFFER),A ;NOT RECEIVING AT THIS TIME
-
- LD HL,TXQ_ENABLES
- LD B,N_EVENTS
- E_CLEAR:
- LD (HL),A ; TURN OFF ALL THE ENABLES OF ALL ...
- INC HL ; ... POSSIBLE EVENTS.
- DJNZ E_CLEAR
-
- ;INIT THE ROUTINE ADDRESSES IN OUR EVENT TABLE
-
- LD HL,R_DELAY
- LD (TXQ_ADDRESSES),HL
- LD HL,R_SLOTTIME
- LD (TXQ_ADDRESSES+2),HL
- LD HL,R_TAIL
- LD (TXQ_ADDRESSES+4),HL
-
- LD A,(CWID)
- CP 0FFH
- JR Z,SKIPID ; NO CWID DEFINED
-
- LD HL,RTCLOCK
- LD (TXQ_ADDRESSES+6),HL ; REAL TIME CLOCK FOR CWID
- ;
- ; ENABLE RTC FOR CWID
- ;
- LD HL,6000 ; MINUTE IN 1/100THS OF SEC
- LD (TXQT_CWID),HL ; GET TIMER VALUE INTO TIMER SLOT
- LD A,1
- LD (TXQE_CWID),A ; ENABLE THIS EVENT
- LD (MINUTES),A ; SEND FIRST AFTER 1 MINUTE
-
- SKIPID:
-
- LD A,50
- LD (TXDELAY),A ; TX DELAY DEFAULT IS 500 MS
- LD A,64
- LD (PERSISTENCE),A ; SET DEFAULT VALUE FOR PERSISTENCE
- LD A,10
- LD (SLOTTIME),A ; AND SLOT TIME DEFAULTS TO 100 MS
- LD A,3
- LD (TAILTIME),A ;TAIL TIMER DEFAULT
-
-
- ; NOW HAVE THE CON AND STA LEDS DO A "DANCE".
-
- EXX
- PUSH HL
- EXX
- POP DE ;WE SAVED THE LOGICALS TELLING US WHICH LEDS
- ;TO FLASH WHEN WE FIGURED OUT THE STACKSIZE.
- ;THIS IS HOW WE KNOW WHICH LEDS TO BLINK.
-
- LD B,6 ;DO IT 6 TIMES (ARBITRARY AS HELL, BUT SHOULD
- ;BE AN EVEN NUMBER SO THAT THE LEDS ARE OFF AT
- ;THE END OF THIS MESS...)
- LD HL,0 ;USE HL AS DOWNCOUNTER
- DANCE0:
- LD A,D
- OR A
- CALL NZ,CON_FLIP
- LD A,E
- OR A
- CALL NZ,STA_FLIP
- DANCE1:
- DEC HL
- LD A,H
- OR L
- JP NZ,DANCE1
-
- DJNZ DANCE0 ;DO THIS 6 TIMES (3 "CYCLES")
-
- ;PREVIOUS STUFF SHOWED THAT THE DOWNLOAD OR BOOT WORKED PROPERLY...
-
-
-
- ;WE RE-INITIALIZE THE SIO PORTS SO THAT WE FLUSH GARBAGE CHARS THAT MAY HAVE
- ;COME IN WHILE WE WERE DIDDLING THE LEDS. THIS IS NECESSARY BECAUSE UNLESS WE
- ;DO THIS, THEN THE A CHANNEL (MODEM) GET RX OVERRUN (ESP IF TNC WAS LISTENING
- ;TO NOISE) AND RX OVERRUN IS VERY BAD - SO BAD, IN FACT, THAT I TURN ON BOTH
- ;CON AND STA AND HALT, BECAUSE THIS SITUATION SHOULD NEVER HAPPEN IN NORMAL
- ;USE. I FLUSH THE B (TTY) CHANNEL IN CASE ANYTHING WAS SENT TO IT IN MID-
- ;STREAM.
-
-
- ;RE-INIT SIO.
-
- IN A,(A_CTL) ;ASSURE WE ARE TALKING TO CH 0
- LD C,A_CTL
- LD B,A_SIZE
- LD HL,A_INIT
- OTIR ;INIT SYNC (MODEM) PORT
-
- ;RE-INIT ASYNC PORT.
-
- IN A,(B_CTL) ;ASSURE WE ARE TALKING TO CH 0
- LD C,B_CTL
- LD B,B_SIZE
- LD HL,B_INIT
- OTIR ;INIT ASYNC PORT & INTERRUPT VECTOR
-
-
- ; PREPARE TO LOAD HI BITS OF INTERRUPT VECTOR
-
- LD A,I_REGISTER
- LD I,A ;SET INTERRUPT PAGE FOR MODE 2 INTS
- IM 2
- EI ;LET 'EM RIP!
-
- ;-----------------------------------------------------------------------------
- ; THIS IS THE BACKGROUND PROGRAM.
- ; NOTE THAT SINCE EVERYTHING ELSE IS INTERRUPT DRIVEN, AND SAVES REGISTERS,
- ; THIS PART OF THE CODE CAN USE REGISTERS & EXPECT VALUES TO STAY.
-
- COMMUTATOR_LOOP:
- ;
- ; SEE IF ID NEEDED
- ;
- LD A,(CWIDFLAG)
- OR A
- JR NZ,TRY_ID
-
- LD A,(TX_OUTSTANDING) ;IF THERE ARE NO OUTSTANDING TX...
- OR A ;...FRAMES, THEN WE DON'T HAVE TO...
- JP Z,SCAN_CHECK ;...WORRY ABOUT TRANSMITTER
-
- TRY_ID:
- ;
- ; IF THERE ARE FRAMES TO TRANSMIT, WE MAY HAVE TURNED ON TXDELAY, OR WE MAY BE
- ; TRANSMITTING A FRAME SO CHECK FIRST.
- ; (THIS BUG FOUND LATE ON 30 SEP 86) THE CLEANEST WAY TO DO
- ; THIS IS TO CHECK IF WE ARE KEYED UP. IF SO, NOTHING ELSE TO DO FOR NOW
- ; HERE. THIS IS THE "LAST BUG!" FOUND AT 11:59PM EDT ON 30 SEP.
-
- LD A,(A_WR5)
- AND RTS
- JP NZ,SCAN_CHECK ;IF TX KEYED UP, NOTHING FOR US TO
- ;DO HERE!
- ;
- ; ELSE WE'VE NOTICED THAT WE'VE GOT SOME FRAME(S) TO SEND.
- ; TRY TO KEYUP TX
-
- LD A,(FULL_DUPLEX)
- OR A
- JP NZ,KEY_UP ;IF FULL DUPLEX, THEN THERE IS NO
- ;NEED TO WORRY ABOUT ALL THIS SILLY
- ;SLOT TIME AND PERSISTENCE STUFF!
-
- LD A,(TXQE_SLOTTIME) ;GET SLOTTIME TIMER ENABLE
- OR A
- JP NZ,SCAN_CHECK ;IF WE'RE WAITING, KEEP WAITING!
-
- ;CHECK IF CARRIER DETECT IS ACTIVE
-
- LD A,(DCD_STATE) ;DCD_STATE IS SET IN INTERRUPT ROUTINE
- OR A
- JP NZ,SCAN_CHECK ;IF CARRIER ACTIVE, WAIT IT OUT
-
- ;SO, DCD IS INACTIVE; DO PERSISTENCE ALGORITHM
-
- LD A,R ;GRAB THE Z-80 REFRESH REGISTER
- ADD A,A ;DOUBLE;NOW 0 <= A REG <= 254
- LD B,A ;B HOLDS OUR "RANDOM" NUMBER
- LD A,(PERSISTENCE)
- SUB B ;A REG = PERSISTENCE - RANDOM #
- JP C,NO_PTT ;IF (P-R) < 0 THEN NO PTT NOW
- ; NOTE THAT P=255 MEANS ALWAYS KEY UP
-
- ;OK, SO WE'VE WON WITH THE RANDOM NUMBER GENERATOR. KEYUP TX AND START THE
- ;TXDELAY TIMER
-
- KEY_UP:
- ;
- ; SEE IF ID NEEDED
- ;
- LD A,(CWIDFLAG)
- OR A
- JP Z,NO_ID
-
- CALL STARTID
-
- JP SCAN_CHECK
-
- NO_ID:
-
- LD A,(TXDELAY)
- LD H,0
- LD L,A ;HL IS 16-BIT VALUE OF TXDELAY
- LD (TXQT_DELAY),HL ;GET TIMER VALUE INTO TIMER SLOT
- LD A,1
- LD (TXQE_DELAY),A ;ENABLE THIS EVENT
-
- LD A,5
- DI ;WE NEED QUITE TIME HERE.
- OUT (A_CTL),A ;;;READY TO WRITE INTO WR5 OF CH A
- LD A,(A_WR5)
- OR RTS ;;;TURN ON THE PTT BIT...
- LD (A_WR5),A ;;;...IN THE MEMORY COPY OF WR5
- OUT (A_CTL),A ;;; KEYUP TRANSMITTER
- EI
- JP SCAN_CHECK ;THAT'S ALL WE DO FOR NOW, WE AWAIT
- ;TXDELAY EVENT
-
- NO_PTT:
- ;
- ; SINCE WE LOST ON RANDOM #, WAIT SLOTTIME BEFORE TRYING AGAIN
- ;
- LD A,(SLOTTIME)
- LD H,0
- LD L,A ;HL HAS 16-BIT VERSION OF SLOTTIME
- LD (TXQT_SLOTTIME),HL ;SET UP THE TIMER VALUE OF THIS EVENT
- LD A,1
- LD (TXQE_SLOTTIME),A ;AND ENABLE THIS EVENT
-
- ; NOTE THAT THIS CODE DOES NOT HAVE TO BE INTERRUPT PROTECTED BECAUSE WE
- ; REALLY DON'T CARE IF THE SLOT TIMER IS DECREMENTED BETWEEN BEING LOADED
- ; AND BEING ENABLED.
-
- SCAN_CHECK:
-
- LD HL,TXQ_ENABLES ; GEAR UP TO CHECK TIMER ROUTINES
- LD IX,TXQ_TIMERS
- LD IY,TXQ_ADDRESSES
- LD DE,2 ;BUMP IX & IY BY TWOS
- LD B,N_EVENTS ;NUMBER OF POSSIBLE EVENTS
- SCAN_TOP:
- LD A,(HL)
- OR A
- JP Z,SCAN_BOTTOM ;IF NOT ENABLED, CHECK NEXT ONE
-
- ;ELSE IS ENABLED. TIMER EXPIRED?
-
- LD A,(IX+1)
- LD C,A ;SAVE MS BYTE FOR POSSIBLE USE LATER
- OR (IX)
- JR Z,SCAN_FIRE ;FIRE THIS IF WE ARE AT 0 COUNT
-
- LD A,C
- OR A ; SAVES US SOME TIME DOING IT THIS WAY
- JP P,SCAN_BOTTOM ; OR FIRE IF WE ARE NEGATIVE
-
- SCAN_FIRE:
- XOR A
- LD (HL),A ;DISABLE THIS EVENT AS IT FIRES
- PUSH HL
- LD HL,SCAN_RETURN ;LOAD UP ROUTINE RETURN ADDRESS
- PUSH HL ;SAVE AS RETURN ADDRESS ON STACK
- LD H,(IY+1)
- LD L,(IY) ;GET ADDRESS OF ROUTINE TO "CALL"
- JP (HL) ;"CALL" THIS ROUTINE
-
- SCAN_RETURN: ;WHERE ALL ROUTINES RETURN
-
- POP HL ;GET ORIGINAL HL BACK
-
- SCAN_BOTTOM:
- INC HL ;INCREMENT ENABLE TABLE POINTER
- ADD IX,DE ;KEEP TIMER TABLE POINTER IN STEP
- ADD IY,DE ;KEEP ROUTINE TABLE POINTER IN STEP
- DJNZ SCAN_TOP ;LOOK AT ALL ENTRIES IN TABLES
-
-
- ;NOW SEE IF WE NEED TO START AN OUTPUT TO RS-232 (HOST) PORT
- LD A,(OUT_STARTED)
- OR A ;ALSO CLEARS CARRY (SEE BELOW)
- JP NZ,COMMUTATOR_LOOP ;IF OUTPUT STARTED, NOTHING TO DO
-
- ; ELSE WE SHOULD CHECK TO SEE IF WE NEED TO START AN OUTPUT
- DI
- CALL CON_OFF ;;;
- LD HL,(OUT_HEAD_CBUF) ;;;GRAB CURRENT TOP OF CIRC BUF PTR
- LD DE,(OUT_TAIL_CBUF) ;;;AND WHERE THE NEXT FREE BUF PTR IS
- EI
- ;INTERRUPT PROTECT THE PICKUP OF THE
- ;TWO POINTERS 3 FEB 87
- OR A
- SBC HL,DE
- JP Z,COMMUTATOR_LOOP ;IF THE SAME, NOTHING TO DO
-
- ;ELSE WE NEED TO START AN OUTPUT
- DI ;INTERRUPT PROTECT THIS SECTION,
- ;ALTHOUGH I'M NOT SURE IT NEEDS IT...
- ;3 FEB 87
- ;NOTE: IT SHOULD ALREADY BE DONE!
- LD HL,(OUT_HEAD_CBUF) ;;;GET POINTER TO NEXT CBUF TO OUTPUT
- LD E,(HL)
- INC HL
- LD D,(HL) ;;;DE HAS POINTER TO BUFFER CHAIN
- LD (OUT_CHAIN_HEAD),DE ;;;SET IN INTERRUPT ROUTINE'S PLACE
- LD A,1
- LD (OUT_STARTED),A ;;;YES, OUTPUT STARTED
-
- CALL CON_ON
- CL_0:
- IN A,(B_CTL) ;;;LOOK AT RR0
- AND TBE ;;;ISOLATE THE TBE BIT
- JR Z,CL_0 ;;;WAIT FOR TRANSMITTER TO GET DONE
-
- LD A,FEND
- OUT (B_DAT),A ;;;SEND FEND CHARACTER (START TXING)
- EI
-
- JP COMMUTATOR_LOOP ;KEEP LOOKING FOR NEW OPPORTUNITY
-
- RTCLOCK:
- ;
- ; COUNT DOWN MINUTES TO KICK OFF CWID
- ;
- LD HL,6000 ; MINUTE IN 1/100THS OF SEC
- LD (TXQT_CWID),HL ; GET TIMER VALUE INTO TIMER SLOT
- LD A,1
- LD (TXQE_CWID),A ; ENABLE THIS EVENT
-
- LD A,(MINUTES)
- DEC A
- LD (MINUTES),A
- RET NZ
- ;
- INC A
- LD (CWIDFLAG),A ; SHOW WE NEED AN ID
-
- RET
- ;
- STARTID:
- ;
- ; SET TIMER TO GO TO NEXT CWID STATE
- ;
- LD HL,IDEVENT
- LD (TXQ_ADDRESSES+6),HL ; REAL TIME EVENT FOR CWID
- ;
- LD HL,6 ; 20HZ BAUD RATE FOR CWID
- LD (TXQT_CWID),HL ; GET TIMER VALUE INTO TIMER SLOT
- LD A,1
- LD (TXQE_CWID),A ; ENABLE THIS EVENT
- ;
- ; RAISE RTS - NEXT TIMER EVENT WILL SEND FIRST BIT
- ;
- LD HL,CWID
- LD (CWIDPTR),HL
-
- XOR A
- LD (CWIDFLAG),A
- LD (LASTBIT),A
- ;
- ; ENTER SYNC MODE SO WE CAN CONTROL TONES
- ;
- DI
- LD A,1
- OUT (A_CTL),A
-
- XOR A
- OUT (A_CTL),A ; INTERRUPTS OFF
-
- LD A,4
- OUT (A_CTL),A
-
- LD A,00010000B ; SYNC
- OUT (A_CTL),A
-
- LD A,6
- OUT (A_CTL),A
-
- LD A,0FFH
- OUT (A_CTL),A ; SYNC CHARS
-
- LD A,7
- OUT (A_CTL),A
-
- LD A,0FFH
- OUT (A_CTL),A ; SYNC CHARS
-
- LD A,5
- OUT (A_CTL),A
-
- LD A,11101011B ; RAISE RTS + TXENABLE
- LD (A_WR5),A
- OUT (A_CTL),A
- ;
- EI
- RET
-
-
-
- IDEVENT:
- ;
- ; 60 MS HAS PASSED - GO TO NEXT STATE
- ;
-
- LD HL,6 ; 20HZ BAUD RATE FOR CWID
- LD (TXQT_CWID),HL ; GET TIMER VALUE INTO TIMER SLOT
- LD A,1
- LD (TXQE_CWID),A ; ENABLE THIS EVENT
- ;
- LD HL,(CWIDPTR)
- LD A,(HL)
- INC HL
- LD (CWIDPTR),HL
-
- CP 0FFH
- JP Z,ENDID
-
- LD HL,LASTBIT
- CP (HL)
- RET Z ; NO CHANGE
-
- LD (HL),A ; SAVE NEW STATE
-
- LD A,7FH
- OUT (A_DAT),A ; TOGGLE TONE
-
- RET
- ;
-
- ENDID:
- ;
- ; RESET REAL TIME EVENT TO COUNT DOWN FOR NEXT ID (29 MINS)
- ;
- PUSH BC
-
- DI
-
- IN A,(A_CTL) ;ASSURE WE ARE TALKING TO CH 0
- LD C,A_CTL
- LD B,A_SIZE
- LD HL,A_INIT
- OTIR ;INIT SYNC (MODEM) PORT
-
- LD A,0E9H
- LD (A_WR5),A
-
- EI
-
- POP BC
-
- LD HL,RTCLOCK
- LD (TXQ_ADDRESSES+6),HL ; REAL TIME CLOCK FOR CWID
- ;
- LD HL,6000 ; MINUTE IN 1/100THS OF SEC
- LD (TXQT_CWID),HL ; GET TIMER VALUE INTO TIMER SLOT
- LD A,1
- LD (TXQE_CWID),A ; ENABLE THIS EVENT
-
- LD A,29
- LD (MINUTES),A
-
- RET
-
- ;*****************************************************************************
- ; TIMER-DRIVEN EVENTS
- ;*****************************************************************************
-
- ;-----------------------------------------------------------------------------
- R_DELAY: ; THIS ROUTINE EXECUTES WHEN THE TX DELAY TIMER EXPIRES.
- PUSH AF
- PUSH BC
- PUSH DE
- PUSH HL
- DI
- CALL TXNEXT_CBUF ;GETS HL TO POINT TO BUFFER CHAIN, AND
- ;SETS TX_CHAIN_HEAD FOR THE INTERRUPT
- ;ROUTINE
- LD A,80H
- OUT (A_CTL),A ;;; RESET TX CRC
- CALL GETCHAR ;;; GETCHAR NEEDS INT. PROTECTION
- OUT (A_DAT),A ;;; SHIP THIS CHAR TO TX MODEM
- LD A,1
- LD (TX_STARTED),A ;;; AND, YES VIRGINA, WE'VE STARTED TX
- LD A,0C0H
- OUT (A_CTL),A ;;; RESET TX UNDERRUN/EOM LATCH
- POP HL
- POP DE
- POP BC
- POP AF
- EI
- RET
-
- ;-----------------------------------------------------------------------------
-
- R_SLOTTIME: ;WHEN SLOTTIME EVENT TIMER EXPIRES, COME HERE.
- RET ; WE WERE JUST WAITING, SO NOTHING
- ; ELSE TO DO HERE (!)
-
- ;-----------------------------------------------------------------------------
-
- R_TAIL: ;WHEN TAIL TIMER TIMES OUT, TURN OFF THE TX
-
- PUSH AF
- LD A,5 ;READY TO WRITE TO WR5 OF CH A
- DI ;;;MUST HAVE ATOMIC USE OF A_WR5 & SIO
- OUT (A_CTL),A ;;;NEXT CHAR TO A_CTL GOES TO WR5
- LD A,(A_WR5) ;;;GRAB A_WR5
- AND 0FFH-RTS ;;;TURN OFF RTS BIT THERE
- LD (A_WR5),A ;;;KEEP MEMORY COPY UPDATED
- OUT (A_CTL),A ;;;AND TURN OFF TX NOW
- EI
- POP AF
- RET
-
- ; INCLUDE IA.MAC ;MODEM INTERRUPT CATCHERS
- ;;;---------------------------------------------------------------------------
- IA_TBE:
- PUSH AF
- PUSH HL
- LD A,(TX_STARTED)
- OR A
- JP Z,IA_T2 ;;; PREVIOUS FRAME FINISHED
-
- LD HL,(TX_CHAIN_HEAD)
- CALL GETCHAR
- LD (TX_CHAIN_HEAD),HL ;;; MUST KEEP THIS POINTER UPDATED
- JR Z,IA_T1 ;;; NO MORE TO SEND
-
- OUT (A_DAT),A ;;; ELSE SHIP THIS CHAR OUT
- IA_T9:
- POP HL
- POP AF
- EI
- RETI ;;; JUST RETURN FROM THESE INTERRUPTS
-
- IA_T1:
- ; HALT ;;;IF IT GETS HERE, HALT
- XOR A
- LD (TX_STARTED),A ;;; TX IS NOT STARTED
- LD HL,TX_OUTSTANDING ;;; MAKE IS SO THAT ONE FEWER FRAMES
- ;;; NOT "(TX_OUTSTANDING)" (!) 29 SEP
- DEC (HL) ;;; ARE OUTSTANDING
- LD A,28H
- OUT (A_CTL),A ;;; RESET TX INTERRUPT PENDING
- JP IA_T9
-
- ;;;PREVIOUS FRAME IS DONE, SIO NOW SENDING A FLAG. MORE?
- IA_T2:
- LD A,(TX_OUTSTANDING)
- OR A
- JP NZ,IA_T21 ;;;IF MORE TO SEND, GO THERE
-
- ;;; ELSE WE'RE DONE HERE, CLEAN UP.
- LD A,28H
- OUT (A_CTL),A ;;; RESET TX INTERRUPT PENDING
-
- ;START TAIL TIMER EVENT
- LD A,(TAILTIME) ;;; { BUG FOUND 30 SEP. IT WAS:
- LD H,0 ;;; "LD HL,(TAILTIME)"
- LD L,A ;;; [OUCH!] }
- LD (TXQT_TAIL),HL ;;; WAIT FOR CRC TO CLEAR TX
- LD A,1 ;;; 8.33 MS/CHAR AT 1200 BPS
- LD (TXQE_TAIL),A ;;; TAILTIME VALUE SHOULD BE >=2.
- JP IA_T9
-
- IA_T21: ;START UP NEXT FRAME
- CALL TXNEXT_CBUF ;;; GET THE NEXT BUFFER CHAIN POINTER
- ;;; SETUP HL AND TX_CHAIN_HEAD
- LD A,80H
- OUT (A_CTL),A ;;; RESET TX CRC GENERATOR
- CALL GETCHAR
- OUT (A_DAT),A ;;;GET 1ST CHAR OF NEXT FRAME
- LD A,1
- LD (TX_STARTED),A ;;; TX STARTED AGAIN
- LD A,0C0H
- OUT (A_CTL),A ;;; RESET TX UNDERRUN/EOM LATCH
- JP IA_T9
-
- ;;;---------------------------------------------------------------------------
- ;;; GOT A CHARACTER FROM THE SIO RX INTERRUPT, DEAL WITH IT
- ;;; EXTENSIVE MODS 3 FEB 87 TO BE IN LINE WITH WHAT I NOW KNOW ABOUT SIO...
-
- IA_RCA:
- PUSH AF
- PUSH HL
-
- LD A,(RX_ALLOCATED_BUFFER)
- OR A
- JP NZ,IA_RC7 ;;; GO THERE IF WE ARE IN "RECEIVING" STATE
-
- ;ELSE WE ARE NOT YET RECEIVING, SO ALLOCATE BUFFER & MAKE US "RECEIVING"
-
- CALL ALLOCATE_BUFFER ;;; GET A NEW BUFFER
- JP Z,RESTART ; BPQ IA_RC5 ;;; NO ROOM, FLUSH THIS FRAME
-
- ;;; IF GOT A BUFFER, INSERT THIS CHARACTER.
- ;;; AFTER DOING INITIAL BUFFER SETUP.
-
- IA_RC6:
- LD (RX_HEAD),HL ;;; SAVE CHAIN HEAD ADDRESS (1ST BUFFER)
- LD (RX_BUF),HL ;;; TUCK AWAY ADDR OF OUR CURRENT BUFFER
- LD A,TRUE
- LD (RX_ALLOCATED_BUFFER),A ;;; AND MARK THAT WE ARE RECEIVING
-
- XOR A
- CALL PUTCHAR ;;; SLIP' FRAME "TYPE" FIELD HERE (ALWAYS 0)
-
- IA_RC7:
- LD HL,(RX_BUF) ;;; LOAD UP ADDRESS OF OUR CURRENT RX BUFFER
- IN A,(A_DAT) ;;; GRAB THE PENDING CHARACTER
- CALL PUTCHAR ;;; AND STUFF IN THIS PARTICULAR BUFFER
- LD (RX_BUF),HL ;;; HL MIGHT HAVE CHANGED IN PUTCHAR()
-
- ;;;*** NOTE! THERE IS A PROBLEM HERE! IF PUTCHAR() HAS NO MORE ROOM, THEN
- ;;; WE NEED TO FLUSH ALL FRAMES SO FAR ACCUMULATED & GO INTO RX_FLUSHING
- ;;; STATE !!! 3 FEB 87
-
- IA_RC9:
- POP HL
- POP AF
-
- EI
- RETI ;;; NOTHING ELSE TO DO HERE
-
-
- ;;; IF NO ROOM, FLUSH THIS FRAME (SIGH)
- ;IA_RC5:
- ; LD A,TRUE
- ; LD (RX_FLUSHING),A ;;; WE ARE IN THE MIDST OF FLUSHING THIS FRAME
- IA_RC2:
- ; CALL STA_ON ;;;DDD NOTE THAT WE ARE IN FLUSHING STATE
- ; IN A,(A_DAT)
- ; IN A,(A_DAT)
- ; IN A,(A_DAT)
- ; IN A,(A_DAT) ;;; EMPTY SIO SILO
- ;
- ; JP IA_RC9
-
-
- ;;;---------------------------------------------------------------------------
- ;;; FROM OUT POINT OF VIEW, THIS INTERRUPT IS ONLY INTERESTING BECAUSE IT
- ;;; TELLS US IF WE'RE AT END OF FRAME.
- IA_SPECIAL:
- PUSH AF
- PUSH HL ;;; REGS WE'LL NEED
-
- LD A,1
- OUT (A_CTL),A ;;; READY TO READ RR1
- IN A,(A_CTL) ;;; OK, GRAB RR1
-
- ;;; FIRST CHECK IF RX OVERRUN. THIS IS VERY BAD, SO HALT.
- BIT 5,A
- JP Z,IA_SP0 ;;; MOST OF THE TIME (ALL THE TIME?) GO THERE
-
- CALL CON_ON
- CALL STA_ON
-
- JP RESTART ; BPQ
-
- IA_SP0:
- BIT 7,A ;;; CHECK STATE OF END OF FRAME BIT
- JP Z,IA_SP8 ;;; ELSE SOMETHING WEIRD HAPPENED - PROBABLY
- ;;; RX OVERRUN. IN ANY CASE, FLUSH THIS FRAME.
- ;;; ERROR RESET & THEN EXIT
- ;;; THAT IS, TREAT LIKE IT WAS A CRC ERROR
-
- ;;; IF END OF FRAME, CHECK CRC BIT FOR VALID.
- IA_SP1:
- BIT 6,A ;;; CHECK CRC ERROR BIT
- JP NZ,IA_SP8 ;;; IF CRC ERROR BIT IS ON, THEN WAS CRC ERROR
-
- ;;; FIRST ENSURE THAT WE INDEED HAVE A BUFFER ALLOCATED...
- LD A,(RX_ALLOCATED_BUFFER)
- OR A
- JP Z,IA_SP9 ;;; IF NO BUFFER ALLOCATED, IGNORE THIS.
-
- ;;; ELSE THIS WAS A GOOD FRAME, AND WE SHOULD SHIP IT OUT TO HOST
- ;;; LEAVE THE FIRST CRC CHARACTER AT END OF BUFFER CHAIN IN THE BUFFER, AS
- ;;; GETCHAR() WILL FLUSH IT.
-
- LD HL,(RX_HEAD)
- CALL OUT_QUEUE_INSERT ;;; SHOVE THIS BUFFER STRING ONTO
- ;;; OUTPUT QUEUE
- XOR A
- LD (RX_ALLOCATED_BUFFER),A ;;; WE DON'T HAVE A BUFFER ALLOCATED
- ;;; FOR THE NEXT FRAME...
- JP IA_SP9
-
- ;;; GET HERE IF THERE WAS A BAD CRC
- IA_SP8:
- LD A,(RX_ALLOCATED_BUFFER) ;;; IF WE DON'T HAVE ANY BUFFERS
- ;;; ALLOCATED, THEN
- OR A ;;;8 FEB - SET CONDITION CODES !!!!!!
- JP Z,IA_SP9 ;;; WE MUST NOT "RELEASE" THEM !!! 10 SEP 86
- ;;; IF THEY ARE NOT ALLOCATED !!!
- IA_SPF:
- XOR A
- LD (RX_ALLOCATED_BUFFER),A ;;; NOT RECEIVING IF WE HAVE BAD CRC
- LD HL,(RX_HEAD)
- CALL FREE_CHAIN ;;; FREE UP ALL BUFFER(S)
-
- IA_SP9:
- LD A,30H ;;; ERROR RESET
- OUT (A_CTL),A
- IN A,(A_DAT) ;;; AVOID SPURIOUS RCA INTERRUPT
-
- ; IN A,(A_DAT) ;;; AVOID SPURIOUS RCA INTERRUPT
- ; IN A,(A_DAT) ;;; AVOID SPURIOUS RCA INTERRUPT
- ; IN A,(A_DAT) ;;; AVOID SPURIOUS RCA INTERRUPT
- ; ;;; AND FLUSH SILO
- POP HL
- POP AF
-
- EI
- RETI
-
- ;;;---------------------------------------------------------------------------
- ;;; FOR EXT/STATUS INTERRUPTS ON MODEM, GET DCD STATE INTO MEMORY, AND
- ;;; DEALLOCATE ANY SPURIOUS BUFFERS (BUFFER STUFF DONE 30 SEP 86).
- IA_EXT:
- PUSH AF
-
- LD A,10H ;;; RESET EXT/STATUS INTERRUPTS
- OUT (A_CTL),A
- IN A,(A_CTL) ;;; GRAB RR0
- AND DCD
- LD (DCD_STATE),A ;;;SAVE FOR TX KEYUP DCD DETECT. IS 0 IF DCD
- ;;;IS NOT ACTIVE, OR NON-ZERO IF IT IS ACTIVE.
-
- ;
- LD A,(RX_ALLOCATED_BUFFER) ;;; IF WE ARE NOT IN THE
- ; ;;; RECEIVING STATE...
- OR A ;;; THEN THERE ARE NO ALLOCATED BUFFERS AND...
- JP Z,IA_EX9 ;;; WE MUST NOT "RELEASE" THEM !!! 10 SEP 86
- ; ;;; IF NO BUFFERS ALLOCATED !!!
- XOR A
- LD (RX_ALLOCATED_BUFFER),A ;;; NOT RECEIVING
- PUSH HL
- LD HL,(RX_HEAD)
- CALL FREE_CHAIN ;;; FREE UP ALL BUFFER(S)
- POP HL
- ;
- ; WE HAVE JUST JUNKED THE FIRST PART OF THE FRAME, BUT THE RECEIVER
- ; MAY WELL STILL BE RUNNING (IF DCD HAS DROPPED WITHOUT LOSS OF
- ; DATA, WHICH CAN HAPPEN WITH STATE MACHINE DCD. IT SEEMS A GOOD
- ; TO RE-ENTER HUNT MODE
- ;
- LD A,33H ; ERROR RESET, WR3
- OUT (A_CTL),A
-
- LD A,0D9H ; ENTER HUNT
- OUT (A_CTL),A
- ;
- IA_EX9:
- POP AF
-
- EI
- RETI
-
- ; INCLUDE IB.MAC ;TTY INTERRUPT CATCHERS
-
- ;;;---------------------------------------------------------------------------
- ;;; WE GET HERE WHENEVER -CTS, -DCD OR -SYNC INPUTS CHANGE, AS WELL AS BREAK
- ;;; DETECTION. SINCE -DCD
- ;;; IS ALWAYS TIED TO +5 VOLTS, WE NEED ONLY WORRY ABOUT -CTS AND -SYNC.
- ;;; -CTS IS WIRED TO PIN 20, DTR, OF THE RS232 CONNECTOR, AND IS SUPPOSED TO
- ;;; BE USED FOR HOST TO TNC HANDSHAKING; WE IGNORE THIS TRANSITION (WE ASSUME
- ;;; THAT THE HOST IS ALWAYS READY). WE ALSO IGNORE BREAK DETECTION. WE ARE
- ;;; ONLY INTERESTED IN -SYNC TRANSITIONS, SO WE CAN KEEP TIME.
- ;;; NOTE! THIS IS THE ONLY ROUTINE THAT IS ALLOWED TO USE THE OTHER REG SET!!
- ;;; DEAL WITH BREAK DETECTION...
-
- SYNC_HUNT EQU 10H
- IB_EXT:
- EX AF,AF'
- EXX ;;; WE WANT THE OTHER REGISTERS
- LD A,10H
- OUT (B_CTL),A ;;; RESET EXT/STATUS INTERRUPTS
- IN A,(B_CTL) ;;; GRAB RR0
- LD D,A ;;; HOLD IT FOR A MOMENT...
- AND SYNC_HUNT ;;; ISOLATE THIS BIT
- JP Z,IB_S0
- ;ELSE SYNC/HUNT IS A 1
- LD A,C
- OR A
- JP Z,IB_S1 ;;; GO HERE IF STATE OF SYNC/HUNT CHANGED
-
-
- ;;; HERE IF SYNC/HUNT BIT DID NOT CHANGE - MAYBE SOMETHING ELSE DID....
- IB_S9:
- LD A,D ;;; RETREIVE RRO FROM ABOVE
- AND BREAK_ABORT ;;; CHECK IF WE ARE DOING A BREAK/ABORT THING
- JP Z,IB_NBA ;;; THERE IF NO BREAK/ABORT
-
- ;;; ELSE BREAK/ABORT BIT ON, NOTE STATE CHANGE...
- LD A,1
- LD (IN_BREAK),A ;;; SAVE IN MEM (PROBABLY CAN USE E REG...)
- IN A,(B_DAT) ;;; CLEAR OUT ANY NULL CHARACTER FROM BUFFER
- JP IB_BOK ;;; BREAK OK FOR NOW...
-
- IB_NBA: ;;;IF NO BREAK/ABORT, CHECK IF WE ARE IN BREAK/ABORT STATE.
- LD A,(IN_BREAK)
- OR A
- JP Z,IB_BOK ;;; NOTHING GOING ON, BREAK OK
-
- ;;; ELSE WE WERE IN BREAK MODE, AND THIS IS THE TAIL END OF A BREAK.
- XOR A
- LD (IN_BREAK),A
- IN A,(B_DAT) ;;; DISCARD THE SINGLE EXTRANEOUS NULL
- IB_BOK:
- IB_S99:
- EX AF,AF'
- EXX
- EI
- RETI ;;; ELSE SOMETHING ELSE & WE DON'T CARE
- IB_S0: ;;; SYNC/HUNT IS A 0
- LD A,C
- OR A
- JP NZ,IB_S1A ;;; GO HERE IF SYNC/HUNT CHANGED
- JP IB_S9 ;;; ELSE NOT INTERESTED, FORGET IT
-
- ;GET HERE IF STATE OF SYNC/HUNT CHANGED
- IB_S1:
- LD C,1
- JP IB_S1B
- IB_S1A: ;;; FIRST FIX UP C FOR NEXT TICK
- LD C,0
- IB_S1B:
- ;;; HERE WHEN WE'VE SEEN A REAL "CLOCK TICK" & DEALT WITH C REG
- INC B
- LD A,B
- CP 12
- JP NZ,IB_S99 ;;; WE ACT ON EVERY 12TH CLOCK TICK...
- LD B,0 ;;; SO RELOAD DIVISOR. THIS GIVE US AN
- ;;; EFFECTIVE INTERRUPT RATE OF 100 HZ
-
- ;;; DECREMENT ALL THE TIMERS
-
- LD HL,(TXQ_TIMERS) ;;; GET FIRST TIMER VALUE, AND ...
- DEC HL ;;; ... DECREMENT IT AS REQUIRED.
- LD (TXQ_TIMERS),HL
-
- LD HL,(TXQ_TIMERS+2) ;;; GET SECOND TIMER VALUE, AND ...
- DEC HL ;;; ... DECREMENT IT AS REQUIRED.
- LD (TXQ_TIMERS+2),HL
-
- LD HL,(TXQ_TIMERS+4) ;;; GET THIRD TIMER VALUE, AND ...
- DEC HL ;;; ... DECREMENT IT AS REQUIRED.
- LD (TXQ_TIMERS+4),HL
-
- LD HL,(TXQ_TIMERS+6) ;;; GET THIRD TIMER VALUE, AND ...
- DEC HL ;;; ... DECREMENT IT AS REQUIRED.
- LD (TXQ_TIMERS+6),HL
-
- JP IB_S99
-
-
- ;;;---------------------------------------------------------------------------
- IB_SPECIAL:
- PUSH AF
- IB_SP9: ;;; NORMAL EXIT
- LD A,30H ;;; ERROR RESET
- OUT (B_CTL),A
- POP AF
- EI
- RETI
-
- ;;;---------------------------------------------------------------------------
- ;;; THE TX HAS BECOME EMPTY, SHOVE A NEW CHARACTER OUT
- IB_TBE:
- PUSH AF ;;; NEW CHAR WILL RETURN IN A
- PUSH HL
-
- LD A,(IB_ESC_MODE)
- OR A
- JP Z,IB_T1 ;;; NOT ESCAPED, SO GO HERE
- ;;; ELSE WE ARE ESCAPED, SO SEND ESCAPED CHAR
- LD A,(IB_CHAR) ;;; CHAR WHICH FOLLOWS ESCAPE
- OR A
- JP Z,IB_T2 ;;; SPECIAL CASE IF AT END OF FRAME, CLEAN UP
- OUT (B_DAT),A
- XOR A
- LD (IB_ESC_MODE),A ;;; GET OUT OF ESCAPED MODE
- JP IB_T9 ;;; ALL FOR NOW...
- IB_T1:
- LD HL,(OUT_CHAIN_HEAD) ;;; WE ARE CURRENTLY ON THIS BUFFER, AS...
- CALL GETCHAR ;;; GETCHAR() NEEDS TO KNOW
- LD (OUT_CHAIN_HEAD),HL ;;; MAYBE HL CHANGED, SO SAVE IT IN CASE
-
- JP Z,IB_TDONE ;;; IF NO MORE CHARS, DEAL WITH THIS
- CP FESC
- JP Z,IB_T1A ;;; DEAL WITH FESC CHAR IN DATA STREAM
- CP FEND
- JP Z,IB_T1B ;;; DEAL WITH FEND CHAR IN DATA STREAM
- ;;; ELSE THIS CHAR IS NOTHING SPECIAL, SO SHOVE IT OUT
-
- OUT (B_DAT),A ;;; SHOVE IT OUT
- JP IB_T9 ;;; IF THIS IS NOT LAST CHAR, ALL FOR NOW
-
- ;;; ELSE THIS IS LAST CHAR, SEND FEND
- IB_TDONE:
- LD A,FEND
- OUT (B_DAT),A
- LD A,1
- LD (IB_ESC_MODE),A ;;; SET SPECIAL ESCAPED MODE BY...
- XOR A
- LD (IB_CHAR),A ;;;... MAKING ESCAPED CHAR A 0
- JP IB_T9 ;;; ALL TILL TX BUFFER GOES EMPTY AGAIN.
-
- ; HERE IF ARE COMPLETELY DONE SENDING FRAME
- IB_T2:
- PUSH DE ;;; NEED THIS FOR A MOMENT
- LD HL,(OUT_HEAD_CBUF)
- INC HL
- INC HL
- LD DE,OUT_BOTTOM
- OR A
- PUSH HL
- SBC HL,DE
- POP HL ;;; THIS MAY BE THE ONE WE WANT
- POP DE
- JP NZ,IB_T2A ;;; YES IT IS!
-
- LD HL,OUT_TOP ;;; ELSE, MAKE A CIRCULAR BUFFER
- IB_T2A:
- LD (OUT_HEAD_CBUF),HL ;;; WE WILL WORK ON THIS ONE NEXT
- XOR A
- LD (OUT_STARTED),A ;;; NOT DOING OUTPUTS ANYMORE
- LD (IB_ESC_MODE),A ;;; !!! NOT IN ESCAPED MODE ANYMORE !!!
-
- LD A,28H ;;; NEEDED FOR ASYNC
- OUT (B_CTL),A ;;; RESET TX INTERRUPT PENDING
-
- IB_T9:
- POP HL
- POP AF
- EI
- RETI ;;; NOW GET OUR BUTTS OUT OF HERE...
-
- ;;; HERE IS FESC IN DATA STREAM
- IB_T1A:
- OUT (B_DAT),A ;;; SHIP FESC CHARACTER TO PORT
- LD A,TFESC ;;; READY WHAT WILL BE NEXT CHAR
- IB_T1Z:
- LD (IB_CHAR),A ;;; SET CHAR FOR NEXT TIME
- LD A,1
- LD (IB_ESC_MODE),A ;;; WE ARE IN ESCAPED MODE
- JP IB_T9 ;;; ALL FOR NOW
-
- ;;; HERE IS FEND IN DATA STREAM
- IB_T1B:
- LD A,FESC
- OUT (B_DAT),A
- LD A,TFEND
- JP IB_T1Z ;;; REST IS SAME AS FESC CASE
-
-
- ;;;---------------------------------------------------------------------------
- ;;; GOT A CHAR FROM THE TTY PORT, DEAL WITH IT.
-
- IB_RCA:
- PUSH AF
-
- IN A,(B_CTL) ;;; READ RR0; FORCE REG POINTER TO BE 0
- LD A,1
- OUT (B_CTL),A ;;; READY TO READ RR1
- IN A,(B_CTL) ;;; GRAB RR1
- AND FRAMING_ERROR ;;; ISOLATE THE FE BIT
- JP Z,IB_RTOP ;;; NO FRAMING ERROR, SO PROCESS THIS CHAR
-
- ;;; ELSE WE HAVE A FRAMING ERROR - IGNORE THIS CHAR & FLUSH THIS FRAME...
- CALL STA_OFF ;;; OFF WITH THE LED!
- IN A,(B_DAT) ;;; FLUSH ERRONEOUS CHARACTER
- XOR A
- LD (IN_STATE),A ;;; FORCE RECEIVER TO LOOK FOR FEND
- LD A,(IN_ALLOCATED_BUFFER)
- OR A
- JP Z,IB_RC9 ;;; IF NO BUFFER IS ALLOCATED, DONE; EXIT.
-
- ;;; ELSE WE WERE RECEIVING A DATA SLIP FRAME, SO FLUSH IT.
- PUSH HL
- LD HL,(IN_HEAD)
- CALL FREE_CHAIN ;;; DUMP THESE BUFFERS BACK TO FREE LIST
- POP HL
- JP IB_RC9 ;;; AND GET OUT OF HERE!
-
- IB_RTOP:
- LD A,(IN_STATE) ;;; GET OUR STATE MACHINE VALUE
- OR A
- JR Z,IB_R0 ;;; IN STATE 0, WAITING FOR FEND
- CP 1
- JR Z,IB_R1 ;;; IN STATE 1, SAW FEND
- CP 2
- JP Z,IB_R2 ;;; IN STATE 2, DATA TO FOLLOW
- CP 3
- JP Z,IB_R3 ;;; SAW FESC, EXPECTING TFESC OR TFEND
- CP 10
- JP Z,IB_R10 ;;; EXPECTING TXDELAY
- CP 20
- JP Z,IB_R20 ;;; EXPECTING P VALUE
- CP 30
- JP Z,IB_R30 ;;; EXPECTING SLOTTIME VALUE
- CP 40
- JP Z,IB_R40 ;;; EXPECTING TAILTIME VALUE
- CP 50
- JP Z,IB_R50 ;;; EXPECTING FULL/HALF DUPLEX VALUE
-
- ;ELSE WE DON'T KNOW WHAT HAPPENED, IGNORE IT.
- IB_RCJUNK:
- IN A,(B_DAT)
- XOR A
- LD (IN_STATE),A ;;;GO INTO IN_STATE 0, FEND HUNT
- IB_RC9:
- POP AF ;;; THROW IT AWAY, WE DON'T NEED JUNK
- EI
- RETI
-
- ;;; HERE IF WE ARE HUNTING FOR FEND CHARACTER
- IB_R0:
- CALL STA_OFF
-
- IN A,(B_DAT)
- CP FEND
- JP NZ,IB_RC9 ;;; IF WE DIDN'T SEE AN FEND, KEEP LOOKING
-
- ;;; ELSE IS AN FEND, CHANGE STATE
- LD A,1
- LD (IN_STATE),A
- JP IB_RC9
-
- ;;; GET HERE IF WE'VE SEEN FEND CHARACTER; LOOK FOR COMMAND BYTE
- IB_R1:
- CALL STA_OFF
- IN A,(B_DAT)
- CP FEND
- JP Z,IB_RC9 ;;; JUST ANOTHER FEND, KEEP LOOKING FOR CMD
-
- CALL STA_ON ;;;GETTING VALID SLIP; SHOW IN STA LED
-
- ;;; HERE IF WE DO NOT HAVE AN FEND (EXPECTING COMMAND BYTE)
- OR A
- JP Z,IB_R1A ;;; 0 COMMAND MEANS DATA WILL FOLLOW
- CP 1
- JP Z,IB_R1B ;;; 1 COMMAND MEANS TXDELAY WILL FOLLOW
- CP 2
- JP Z,IB_R1C ;;; 2 COMMAND MEANS P(PERSISTENCE) WILL FOLLOW
- CP 3
- JP Z,IB_R1D ;;; 3 COMMAND MEANS SLOT TIME WILL FOLLOW
- CP 4
- JP Z,IB_R1E ;;; 4 COMMAND MEANS TAILTIME TO FOLLOW
- CP 5
- JP Z,IB_R1F ;;; 5 COMMAND MEANS FULL/HALF DUPLEX TO COME
-
- ;;; HERE IF WE RECEIVE BOGUS COMMAND BYTE, FLUSH REST OF FRAME
-
- CALL STA_OFF ;;;BOGOSITY, SO TURN OFF STA LED
-
- XOR A
- LD (IN_STATE),A ;;; GO TO STATE WHICH LOOKS FOR FEND
- JP IB_RC9
-
- ;;; DATA ARE EXPECTED, CHANGE STATE
- IB_R1A:
- LD A,2
- LD (IN_STATE),A
- JP IB_RC9
-
- ;;; TXDELAY TO FOLLOW, CHANGE STATE
- IB_R1B:
- LD A,10
- LD (IN_STATE),A
- JP IB_RC9
-
- ;;; P TO FOLLOW, CHANGE STATE
- IB_R1C:
- LD A,20
- LD (IN_STATE),A
- JP IB_RC9
-
- ;;; SLOTTIME TO FOLLOW, CHANGE STATE
- IB_R1D:
- LD A,30
- LD (IN_STATE),A
- JP IB_RC9
-
- ;;; TAILTIME TO FOLLOW, CHANGE STATE
- IB_R1E:
- LD A,40
- LD (IN_STATE),A
- JP IB_RC9
-
-
- ;;; FULL/HALF DUPLEX TO FOLLOW, CHANGE STATE
- IB_R1F:
- LD A,50
- LD (IN_STATE),A
- JP IB_RC9
-
-
- ;;; THESE BYTES ARE DATA
- IB_R2:
- IN A,(B_DAT)
- CP FEND
- JR Z,IB_R2B ;;; FEND MEANS TO QUEUE THIS BUFFER
- PUSH AF ;;; SAVE THE CHAR WE READ ON STACK FOR A BIT..
-
- LD A,(IN_ALLOCATED_BUFFER)
- OR A
- JP NZ,IB_R2C ;;; IF WE ALREADY ALLOCATED BUFFER
-
- PUSH HL
- CALL ALLOCATE_BUFFER ;;; GET OUR INITIAL BUFFER TO MESS WITH
- JP NZ,IB_R22
-
- ;;;ELSE NO ROOM, FLUSH THIS FRAME
-
- POP HL ;;; KEEP STACK TIDY
- XOR A
- LD (IN_STATE),A
- JP IB_RC9
-
- IB_R22:
- LD A,1
- LD (IN_ALLOCATED_BUFFER),A ;;; MAKE OURSELVES ACTIVE
-
- LD (IN_BUFFER),HL
- LD (IN_HEAD),HL ;;; SAVE CURRENT & HEAD OF CHAIN POINTERS
- POP HL
-
- IB_R2C:
- POP AF ;;; RETREIVE THE DATA CHAR WE JUST GOT...
- CP FESC
- JR Z,IB_R2A ;;; IF FESC IN DATA STREAM, SWITCH STATE
-
- PUSH HL
- LD HL,(IN_BUFFER)
- CALL PUTCHAR ;;; SHOVE THIS CHARACTER INTO OUR BUFFER
- LD (IN_BUFFER),HL ;;; SAVE IN CASE HL CHANGED
- POP HL
- JP IB_RC9 ;;; DONE SO FAR
-
- ;;; FESC CHARACTER SEEN WHILE GRABBING DATA
- IB_R2A:
- LD A,3
- LD (IN_STATE),A ;;; GO TO THIS OTHER STATE
- JP IB_RC9
-
- ;;; FEND CHARACTER SEEN WHILE GRABBING DATA
- IB_R2B:
- LD A,(IN_ALLOCATED_BUFFER)
- OR A
- JR Z,IB_R2Z ;;; NO BYTES ACCUMULATED, SO IS NULL FRAME
-
- ;;; ELSE WE MUST SHIP THIS FRAME TO TX
- PUSH HL ;;; THIS BUG FOUND 29 SEP (MUST SAVE HL !!!)
- LD HL,(IN_BUFFER)
- CALL PUTCHAR ;;; PUT A GARBAGE CHARACTER AT THE END OF
- ;;; LAST BUFFER BECAUSE GETCHAR() WILL STRIP
- ;;; IT. HACK NEEDED BECAUSE OF RX USE OF
- ;;; PUTCHAR/GETCHAR.
- LD HL,(IN_HEAD)
- CALL TX_QUEUE_INSERT
- POP HL
- XOR A
- LD (IN_ALLOCATED_BUFFER),A ;;; INPUT NO LONGER ACTIVE
- IB_R2Z: ;;; ENTRY POINT FOR NULL FRAME
- LD A,1 ;;; KEEP AS WAS, FENDS ONLY AT END IN V.32
- LD (IN_STATE),A ;;; GO LOOK FOR ANOTHER FRAME
-
- CALL STA_OFF ;;;DONE GETTING THIS FRAME, TURN STA LED OFF
-
- JP IB_RC9
-
-
- ;;; HERE IF WE'VE SEEN FESC IN DATA STREAM
- IB_R3:
- IN A,(B_DAT)
- CP TFESC
- JR Z,IB_R3A
- CP TFEND
- JR Z,IB_R3B
-
- ;;; ELSE WE DON'T KNOW WHAT THE HELL IT IS, SO IGNORE & KEEP COLLECTING BYTES
- LD A,2
- LD (IN_STATE),A ;;; GO BACK INTO "DATA RECEIVING" STATE
- JP IB_RC9
-
- ;;; HERE IF WE'VE SEEN TFESC AFTER AN FESC IN DATA STREAM; WRITE AN FESC
- IB_R3A:
- LD A,FESC
- IB_R3Z:
- PUSH HL
- LD HL,(IN_BUFFER)
- CALL PUTCHAR
- LD (IN_BUFFER),HL
- POP HL
- LD A,2
- LD (IN_STATE),A ;;; GET OUT OF ESCAPED MODE
- JP IB_RC9
-
- ;;; HERE IF WE'VE SEEN TFEND AFTER FESC IN DATA STREAM; WRITE FEND
- IB_R3B:
- LD A,FEND
- JP IB_R3Z ;;; REST IS SAME AS FOR TFESC CASE
-
-
- ;;; THIS CHARACTER IS INTERPRETED AS TXDELAY
- IB_R10:
- IN A,(B_DAT)
- LD (TXDELAY),A
- XOR A
- LD (IN_STATE),A ;;; GO BACK TO FEND HUNT STATE
- JP IB_RC9
-
- ;;; THIS CHARCTER IS P, PERSISTENCE VALUE
- IB_R20:
- IN A,(B_DAT)
- LD (PERSISTENCE),A
- XOR A
- LD (IN_STATE),A ;;; GO BACK TO FEND HUNT STATE
- JP IB_RC9
-
- ;;; THIS CHARACTER IS SLOTTIME VALUE
- IB_R30:
- IN A,(B_DAT)
- LD (SLOTTIME),A
- XOR A
- LD (IN_STATE),A ;;; GO BACK TO FEND HUNT STATE
- JP IB_RC9
-
-
- ;;; THIS CHARACTER IS TAILTIME VALUE
- IB_R40:
- IN A,(B_DAT)
- LD (TAILTIME),A
- XOR A
- LD (IN_STATE),A ;;; GO BACK TO FEND HUNT STATE
- JP IB_RC9
-
-
- ;;; THIS CHARACTER IS FULL/HALF DUPLEX VALUE
- ;;; 0 MEANS HALF DUPLEX, NON-ZERO MEANS FULL DUPLEX
- IB_R50:
- IN A,(B_DAT)
- LD (FULL_DUPLEX),A
- XOR A
- LD (IN_STATE),A ;;; GO BACK TO FEND HUNT STATE
- JP IB_RC9
-
- ; INCLUDE BUFFERS.MAC ;ALL BUFFER-RELATED STUFF IN HERE
- ;PLUS ALL (EVENTUALLY) VARIABLES
- ;
- ; THE BUFFER LIST IS KEPT FROM "BOTTOM" TO THE END OF RAM. THE FORMAT OF THE
- ; BUFFERS IS:
-
- ;+------+--------+-------+---------------------------------------------------+
- ;| NEXT | NBYTES | NREAD | DATA |
- ;+------+--------+-------+---------------------------------------------------+
- ;
- ; 2 BYTES 1 BYTE 1 BYTE 124 BYTES (TOTAL 128 BYTES)
-
- ; NEXT POINTER TO NEXT BUFFER ON THIS BUFFER CHAIN (OR 0 IF NO MORE)
- ; NBYTES NUMBER OF BYTES IN THIS BUFFER THAT ARE VALID
- ; NREAD NUMBER OF BYTES READ FROM THIS BUFFER (USED BY GETCHAR)
- ; DATA 124 BYTES OF DATA (NOT ALL IS NECESSARILY VALID, SEE NBYTES FIELD)
- ;
- ; THE BUFFER POOL IS ALL HERE, AND AS PROCESSES NEED BUFFER SPACE, IT IS ALL
- ; ALLOCATED OUT OF THIS POOL. SEE ALLOCATE_BUFFER AND FREE_BUFFER CODE.
-
-
- ;;;---------------------------------------------------------------------------
- ;;; RETURN IN HL A POINTER TO A FREE BUFFER. IF THERE ARE NOT MORE BUFFERS,
- ;;; RETURN WITH Z FLAG SET.
- ;;; DESTROYS NO REGISTERS EXCEPT RETURN VALUE HL.
- ;;; IS CALLED FROM AN INTERRUPT ROUTINE, SO THIS OPERATION IS ATOMIC.
-
- ALLOCATE_BUFFER:
-
- PUSH BC
- PUSH AF
-
- LD HL,(FREE) ;;;GET POINTER TO HEAD OF FREE LIST
- LD A,H
- OR L
- JP NZ,OK_ALLOCATE_BUFFER ;;; ASSURE WE'RE NOT OFF THE END
-
- ;GET HERE IF NO MORE BUFFERS. RETURN Z SET - DO NOT DISTURB A.
-
- POP AF
- LD B,A ;;; TUCK A AWAY FOR A MOMENT...
- XOR A ;;; TURN ON Z BIT
- LD A,B ;;; RETREIVE ORIGINAL A
- POP BC
- RET
-
- OK_ALLOCATE_BUFFER:
-
- XOR A
- LD C,(HL) ;;;GRAB LO BYTE OF NEXT FREE BUFFER
- LD (HL),A ;;; CLEAR IT OUT
- INC HL
- LD B,(HL) ;;; "LD BC,(HL)" NOW HI BYTE
- LD (HL),A ;;; CLEAR IT OUT, TOO
- LD (FREE),BC ;;; UPDATE WITH NEW FREE LIST POINTER
-
- DEC HL ;;; NOW HL IS AT HEAD OF NEW BUFFER
-
- POP AF
- LD B,A ;;; TUCK A AWAY FOR A MOMENT...
- LD A,1
- OR A ;;; TURN Z BIT OFF (I.E., ALL OK)
- LD A,B ;;; RETREIVE ORIGINAL A
-
- POP BC
- RET
-
- ;;;---------------------------------------------------------------------------
- ;;; FREE_BUFFER GETS PASSED A POINTER (IN HL) TO A BUFFER TO BE FREED. THE
- ;;; BUFFER IS PLACED ON THE HEAD OF THE FREE LIST. THE NBYTES & NREAD FIELDS
- ;;; ARE MADE 0 BEFORE PLACING ON FREE LIST.
- ;;; THIS ROUTINE IS CALLED AT INTERRUPT LEVEL, SO RESULTS ARE ATOMIC.
- ;;; NO REGISTERS ARE DISTURBED AT ALL. THE FREE POINTER IS UPDATED, HOWEVER.
- ;;; 159 T STATES [ 63.6 USEC @ 2.5 MHZ ]
-
- FREE_BUFFER:
- PUSH AF
- PUSH BC ;;;WE'LL USE THESE
- PUSH HL ;;;THIS WILL BE NEW HEAD OF FREE LIST
-
- LD BC,(FREE) ;;;GET OLD FREE HEAD
- LD (HL),C ;;;PUT ON FREE CHAIN, FIRST LOW BYTE...
- INC HL
- LD (HL),B ;;; ...NOW HI BYTE
- XOR A
- INC HL
- LD (HL),A ;;; ZERO OUT NBYTES FIELD
- INC HL
- LD (HL),A ;;; AND THE NREAD FIELD OF NEW HEAD OF FREE
-
- POP HL ;;;GET NEW HEAD OF FREE LIST BACK
- LD (FREE),HL ;;;AND SAVE IT IN MEMORY WHERE IT BELONGS
-
- POP BC
- POP AF
- RET
- ;;; --------------------------------------------------------------------------
- ;;; PUTCHAR - HL CONTAINS POINTER TO BUFFER, A CONTAINS THE CHARACTER TO PUT
- ;;; INTO THE BUFFER. UPON RETURN, CHAR IS PUT INTO THIS BUFFER IF THER IS
- ;;; ROOM, ELSE ANOTHER BUFFER IS ALLOCATED AND HL IS UPDATED TO POINT TO THIS
- ;;; NEW BUFFER. THE NEW BUFFER IS CHAINED ONTO THE OLD BUFFER IN THIS CASE.
- ;;; THE CALLING ROUTINE IS RESPONSIBLE FOR MAINTAING BOTH THE HEAD OF A
- ;;; PARTICULAR BUFFER CHAIN (IF IT NEEDS IT), AND THE CURRENT BUFFER BEING
- ;;; MANIPULATED. THIS ROUTINE IS CALLED AT INTERRUPT LEVEL, SO IS ATOMIC. NO
- ;;; REGISTERS DISTURBED, EXCEPT THAT HL MAY HAVE A NEW VALUE.
- ;;; 211 T STATES [ 84.4 USEC @ 2.5 MHZ ] NO NEW BUFFER REQUIRED
- ;;; 338 T STATES [ 135.2 USEC @ 2.5 MHZ ] NEW BUFFER NEEDED
-
- PUTCHAR:
- PUSH BC
- PUSH IX
- PUSH AF
- PUSH HL ;;;DO IT THIS WAY FOR A REASON...
-
- POP IX ;;;GET BUFFER POINTER INTO IX
- LD A,(IX+2) ;;;GRAB NBYTES FIELD
- CP 124 ;;;MAX OF 124 CHARS IN A BUFFER
- CALL Z,PUTC_NEED_NEW_BUFFER
- ;;; IF IT TAKES THIS CALL, IT RETURNS WITH A NEW BUFFER, WITH HL POINTING TO
- ;;; IT (AS WELL AS IX), AND WITH A REG SET TO 0.
- ;;; ELSE JUST PLUNK INTO BUFFER
- INC (IX+2) ;;;ONE MORE CHAR WILL GO INTO THIS BUFFER
- LD C,A ;;;GET PREVIOUS NBYTES
- XOR A
- LD B,A ;;; BC <- NBYTES, FILLED OUT TO 16 BITS
- ADD IX,BC ;;; UPDATE IX TO POINT TO WHERE CHAR GOES
- POP AF ;;; RETREIVE THE CHAR WE WANT TO SAVE
- LD (IX+4),A ;;; SAVE IT IN THIS BUFFER
-
- POP IX
- POP BC
- RET ;;;DONE FOR THE MOMENT
-
- ;;; 127 T STATES [ 50.8 USEC @ 2.5 MHZ ] (REALLY PART OF PREV ROUTINE)
- PUTC_NEED_NEW_BUFFER: ;;;PREV BUFFER FILLED, GET A NEW ONE
- PUSH DE ;;; WORKING REGISTERS
- PUSH HL ;;; SAVE CURRENT BUFFER POINTER
- CALL ALLOCATE_BUFFER ;;; GRAB A NEW BUFFER, ADDR IS IN HL
-
- JP Z,RESTART ; NO BUFFERS - RESET WHOLE SYSTEM
-
- EX DE,HL ;;; "LD DE,HL" - GET NEW ADDR INTO DE FOR NOW
- POP HL
- LD (HL),E ;;; LINK NEW BUFFER ONTO CHAIN, LO BYTE FIRST
- INC HL
- LD (HL),D ;;; NOW HI BYTE, CHAINING DONE
-
- EX DE,HL ;;; UPDATE HL FOR ORIG. CALLING ROUTINE'S USE
- PUSH HL
- POP IX ;;; UPPER ROUTINE NEEDS IX POINTING TO NEW BUF
- XOR A ;;; AND A IS NBYTES IN CALLING ROUTINE, MAKE..
- ;;; ZERO FOR A NEW BUFFER
- POP DE ;;; DONE WITH THIS WORKING REGISTER
- RET ;;; ALL DONE HERE, LET CALLING ROUTINE FINISH
-
- ;;; --------------------------------------------------------------------------
- ;;; GETCHAR - GRAB A CHARACTER FROM THE BUFFER POINTED AT BY HL, RETURN IN A.
- ;;; IF THE "NREAD" FIELD OF THIS BUF = "NBYTES" THEN THIS BUFFER IS EXHAUSTED,
- ;;; SO FOLLOW THE CHAIN ON TO THE NEXT BUFFER & RELEASE OLD BUFFER. IF THE
- ;;; NEXT CHAIN IS 0, OR IF THE NBYTES FIELD IS >= NREAD FIELD, THEN THERE ARE
- ;;; NO MORE BYTES. IN THIS CASE, RETURN WITH Z BIT SET; NORMALLY RETURN WITH
- ;;; Z BIT RESET (THAT IS, NON-ZERO) INDICATING A VALID CHAR IS IN A. NOTE
- ;;; THAT IF WE NEED TO FOLLOW THE CHAIN TO A NEW BUFFER, HL WILL BE UPDATED,
- ;;; TOO, SO THAT THE CALLING ROUTINE NEEDS TO DEAL WITH THIS.
- ;;; NO REGISTERS CHANGED EXCEPT AF AND POSSIBLY HL.
- ;;; CALLED AT INTERRUPT LEVEL, SO OPERATION IS ATOMIC.
- ;;; 212 T STATES [ 84.8 USEC @ 2.5 MHZ ] NO NEW BUFFER NEEDED
- ;;; 493 T STATES [ 197.2 USEC @ 2.5 MHZ ] IF FOLLOWING CHAIN
-
- GETCHAR:
- PUSH IX ;;; SAVE BECAUSE IS WORKING REG
- PUSH BC ;;; WORKING REGS HERE
-
- PUSH HL
- POP IX ;;; IX POINTS TO THIS BUFFER
-
- LD A,(IX+3) ;;; GRAB NREAD
- CP (IX+2) ;;; COMPARE WITH NBYTES
- CALL Z,GETC_NEW_BUF ;;; IF THEY ARE SAME, THIS BUFFER IS SPENT
-
- INC (IX+3) ;;; WE ARE READING ONE MORE CHAR, UPDATE NREAD
- INC A
- CP (IX+2)
- JP NZ,GETC_PLUCK_CHARACTER ;;; IF NOT LOOKING AT LAST CHARACTER
-
- ;;; ELSE, IS THE "NEXT" POINTER 0?
- PUSH HL
- LD B,A ;;; !!!!! SAVE A REG !!!!!!! 4 JAN 87
- LD A,(HL)
- INC HL
- OR (HL)
- LD A,B ;;; !!!! RESTORE A REG (GASP!)
- POP HL
- JR NZ,GETC_PLUCK_CHARACTER
-
- ;;; ELSE NEXT IS 0 AND WE ARE ON LAST CHAR - FLUSH IT & QUIT
- CALL FREE_BUFFER
- POP BC
- POP IX
- RET ;;; NOTE THAT Z BIT IS SET (FROM ABOVE)
-
- ;;; ELSE WE CAN JUST PLUCK A CHARACTER OUT OF THIS BUFFER
- GETC_PLUCK_CHARACTER:
- DEC A ;;; FIX A FROM ABOVE MUCKING AROUND...
-
- LD C,A ;;; GET OLD NREAD INTO BC
- LD B,0 ;;; DITTO
- ADD IX,BC ;;; FIX BUFFER POINTER
- LD A,1
- OR A ;;; MAKE Z BIT RESET
- LD A,(IX+4) ;;; GET THE DESIRED BYTE
-
- POP BC
- POP IX
- RET ;;; ALL FOR THIS SIMPLE CASE
-
- ;;; OLD BUFFER IS SPENT, GET NEW ONE (IF ANY)
-
- GETC_NEW_BUF:
- PUSH DE ;;; NEED THIS REG HERE
- LD E,(HL) ;;; GET LO BYTE OF NEXT POINTER
- INC HL
- LD D,(HL) ;;; HI BYTE OF NEXT POINTER (NOW ALL IN DE)
- DEC HL ;;; HL NOW BACK TO POINT AT SPENT BUFFER
- CALL FREE_BUFFER ;;; GIVE THE BUFFER BACK
-
- EX DE,HL ;;; "LD HL,DE" - FOLLOW CHAIN
- PUSH HL
- POP IX ;;; INIT NEW IX (SAME AS HL IN THIS ROUTINE)
- XOR A ;;; A HOLDS NREAD (NEEDED ABOVE)
- POP DE ;;; RELEASE DE FROM USE BY THIS EXCURSION
- RET
-
- ;;; --------------------------------------------------------------------------
- ;;; FREE_CHAIN - MUST BE CALLED FROM INTERRUPT ROUTINE TO GUARANTEE
- ;;; ATOMICITY. TAKES BUFFER CHAIN POINTED AT BY HL AND RETURNS THEM TO FREE
- ;;; BUFFER LIST
- ;;; 303 T STATES + (N_ON_CHAIN-1)*238 T STATES
- ;;; [ 121.2 USEC + (N_ON_CHAIN-1)*95.2 USEC ]
-
- FREE_CHAIN:
- PUSH AF
- PUSH DE
- PUSH HL ;;; WE WILL MUCK WITH THESE
-
- FC_0:
- LD E,(HL) ;;; GET LO PART OF NEXT BUFFER POINTER
- INC HL
- LD D,(HL) ;;; NOW HI PART OF NEXT BUFFER POINTER
- DEC HL
- CALL FREE_BUFFER ;;; RELEASE THIS BUFFER
- LD A,D
- OR E
- JP Z,FC_9 ;;; IF "NEXT" ADDRESS IS 0, WE ARE AT END
- ;;; ELSE WE'VE GOT MORE ON THIS CHAIN - DEAL WITH THEM.
- EX DE,HL ;;; "LD HL,DE" - HL POINTS TO "NEXT"
- JP FC_0
-
- FC_9:
- POP HL
- POP DE
- POP AF
- RET
-
- ;;; --------------------------------------------------------------------------
- ;;; OUT_QUEUE_INSERT - PLACES THE JUST-RECEIVED BUFFER ON THE OUTPUT QUEUE.
- ;;; THE ADDRESS OF THE RX BUFFER JUST RECEIVED IS IN HL.
- ;;; THE OUTPUT QUEUE IS A CIRCULAR BUFFER. THE OUTPUT ROUTINE KEEPS SENDING
- ;;; OUT BUFFERS UNTIL ITS OUT_HEAD_CBUF POINTER EQUALS ITS OUT_TAIL_CBUF
- ;;; POINTER. THE OUTPUT ROUTINE NEVER MUCKS WITH THE OUT_TAIL_CBUF POINTER;
- ;;; SIMILARLY, THIS ROUTINE NEVER CHANGES THE OUT_HEAD_CBUF POINTER. SO IT
- ;;; IS POSSIBLE TO
- ;;; INSERT NEW ENTRIES INTO THE OUTPUT CIRCULAR BUFFER QUEUE WITHOUT
- ;;; DISTURBING THE ENTRY WHICH IS BEING SENT TO THE OUTPUT PORT.
-
- OUT_QUEUE_INSERT:
- PUSH AF
- PUSH DE
- PUSH HL ;;; USE THESE
-
- EX DE,HL ;;; "LD DE,HL" - MOVE BUFFER TO LINK ADDR
- LD HL,(OUT_TAIL_CBUF) ;;; GRAB NEXT FREE LOCATION
- LD (HL),E ;;; SET LO ADDR 1ST
- INC HL
- LD (HL),D ;;; NOW HI ADDR
- INC HL ;;; NOW HL POINTS TO NEXT FREE ENTRY IN...
- LD DE,OUT_BOTTOM ;;; ...CIRC BUF, UNLESS WE'RE AT END
- OR A ;;; CLEAR CARRY
- PUSH HL ;;; (MAY BE BE NEEDED ADDRESS)
- SBC HL,DE
- POP HL ;;; GET BACK WHAT WE THINK IS GOOD
- JP NZ,OQI_0
-
- LD HL,OUT_TOP ;;; GET HERE IF WE'RE AT END OF CIRC BUFFER.
- OQI_0:
- LD (OUT_TAIL_CBUF),HL
- POP HL
- POP DE
- POP AF ;;; KEEP CLEAN
- RET
-
-
- ;;;---------------------------------------------------------------------------
- ;;; TX_QUEUE_INSERT - SIMILAR TO OUT_QUEUE_INSERT, BUT WITH DIFFERENT QUEUE.
- ;;; ALSO, INCREMENTS THE BYTE TX_OUTSTANDING (WHICH COUNTS THE NUMBER OF
- ;;; FRAMES READY TO BE DUMPED TO THE MODEM PORT). THIS ROUTINE, LIKE
- ;;; OUT_QUEUE_INSERT, DOES NOT NEED TO WORRY ABOUT QUEUE WRAP-AROUND BECAUSE
- ;;; THERE ARE MORE ENTRIES IN EACH OF THESE QUEUES THAN THERE ARE BUFFERS
- ;;; AVAILABLE. YES, I KNOW THIS IS A HACK, AND WASTES SOME RAM SPACE, BUT IT
- ;;; MEANS I DON'T HAVE TO CHECK FOR OVERFLOWS HERE.
- ;;; THE QUEUE IS CIRCULAR, AND SOMETIMES I CALL IT A "CBUF" - CIRCULAR BUFFER
-
- TX_QUEUE_INSERT:
- PUSH AF
- PUSH DE
- PUSH HL
- EX DE,HL ;;; "LD DE,HL" - SAVE CHAIN HEAD IN DE
- LD HL,(TX_TAIL_CBUF) ;;; NEXT FREE LOCATION IN TX CBUF
- LD (HL),E
- INC HL
- LD (HL),D ;;; PUT THIS CHAIN INTO TX QUEUE
- INC HL ;;; HL IS NEXT AVAILBLE TX QUEUE ...
- LD DE,TX_BOTTOM ;;; ... UNLESS WE ARE AT BOTTOM OF ...
- OR A ;;; ... THE TX QUEUE
- PUSH HL
- SBC HL,DE
- POP HL
- JP NZ,TQI_0 ;;; GO THERE IF NOT AT BUFFER BOTTOM
-
- LD HL,TX_TOP ;;; ELSE RELOAD WITH TOP OF QUEUE VAL
- TQI_0:
- LD (TX_TAIL_CBUF),HL ;;; SAVE NEXT FREE QUEUE SLOT
- LD HL,TX_OUTSTANDING
- INC (HL) ;;; +1 MORE FRAME OUTSTANDING NOW
- POP HL
- POP DE
- POP AF
- RET
-
- ;-----------------------------------------------------------------------------
- ; SETUP HL & TX_CHAIN_HEAD FOR TRANSMISSION OF NEXT CHAIN.
-
- TXNEXT_CBUF:
- PUSH AF
- PUSH DE
- LD HL,(TX_HEAD_CBUF)
- LD E,(HL)
- INC HL
- LD D,(HL) ; DE -> NEXT CHAIN TO TRANSMIT
- INC HL ; HL MIGHT BE NEXT CBUF ENTRY POINTER
- PUSH DE
- LD DE,TX_BOTTOM
- OR A ;CLEAR CARRY
- PUSH HL ;SAVE WHAT MIGHT BE CORRECT VALUE
- SBC HL,DE
- POP HL
- POP DE
- JP NZ,TXN_1 ;GO THERE IF NOT AT END OF CIRC. BUF
-
- LD HL,TX_TOP ;ELSE WE WRAP AROUNE
- TXN_1:
- LD (TX_HEAD_CBUF),HL ;SAVE NEXT CIRC BUF POINTER IN MEM
- EX DE,HL ;RETURN PTR TO NEXT CHAIN TO TX IN HL
- LD (TX_CHAIN_HEAD),HL ;TX RCA ROUTINE NEEDS THIS
- POP DE
- POP AF
- RET
-
-
- ;-----------------------------------------------------------------------------
- STA_ON: ;TURN THE STA LED ON. ASSUMES THAT INTERRUPTS ARE DISABLED!
- PUSH AF
- LD A,5
- OUT (A_CTL),A ;;; READY TO WRITE WR5
- LD A,(A_WR5) ;;; GET MEMORY COPY
- AND 0FFH-ALED ;;; SET DTR BIT TO 0 SO LED GOES ON
- OUT (A_CTL),A ;;; ACTUALLY TURN ON STA LED NOW...
- LD (A_WR5),A ;;; UPDATE MEMORY COPY
- POP AF
- RET
- ;-----------------------------------------------------------------------------
- STA_OFF: ;TURN THE STA LED OFF. ASSUMES THAT INTERRUPTS ARE DISABLED!
- PUSH AF
- LD A,5
- OUT (A_CTL),A ;;; READY TO WRITE WR5
- LD A,(A_WR5) ;;; GET MEMORY COPY
- OR ALED ;;; SET DTR BIT TO 1 SO LED GOES OFF
- OUT (A_CTL),A ;;; ACTUALLY TURN OFF STA LED NOW...
- LD (A_WR5),A ;;; UPDATE MEMORY COPY
- POP AF
- RET
-
- ;THESE ROUTINES MUST BE CALLED WITH INTERRUPTS DISABLED!
- ;-----------------------------------------------------------------------------
- STA_FLIP:
- PUSH AF
- PUSH BC
- IN A,(A_CTL) ;;;ASSURE WE ARE TALKING TO CH 0
- LD A,5
- OUT (A_CTL),A ;;; READY TO WRITE WR5
- LD A,(A_WR5) ;;; GET MEMORY COPY
- LD B,A ;;; SAVE ORIGINAL FOR A MOMENT...
- AND ALED ;;; CHECK THE STA LED BIT
- LD A,B ;;; RETREIVE ORIGINAL
- JP Z,STA_F0 ;;; BIT IS A 0, SO LED IS ON, MAKE OFF
- ;ELSE MAKE IT GO ON (BECAUSE IT IS NOW OFF)
- AND 0FFH-ALED ;;; SET DTR BIT TO 0 SO LED GOES ON
- JP STA_F1
- STA_F0:
- OR ALED ;;; SET DTR BIT TO 1 SO LED GOES OFF
- STA_F1:
- OUT (A_CTL),A ;;; ACTUALLY TURN OFF STA LED NOW...
- LD (A_WR5),A ;;; UPDATE MEMORY COPY
- POP BC
- POP AF
- RET
-
- ;-----------------------------------------------------------------------------
- CON_ON:
- PUSH AF
- LD A,5
- OUT (B_CTL),A
- LD A,BLEDON
- LD (B_WR5),A ;;; SAVE IN MEM FOR FLIP ROUTINE
- OUT (B_CTL),A
- POP AF
- RET
- ;-----------------------------------------------------------------------------
- CON_OFF:
- PUSH AF
- LD A,5
- OUT (B_CTL),A
- LD A,BLEDOFF
- LD (B_WR5),A ;;; SAVE IN MEM FOR FLIP ROUTINE
- OUT (B_CTL),A
- POP AF
- RET
- ;-----------------------------------------------------------------------------
- CON_FLIP:
- PUSH AF
- PUSH BC
- IN A,(B_CTL) ;;;ASSURE WE ARE TALKING TO CH 0
- LD A,5
- OUT (B_CTL),A ;;; READY TO WRITE WR5
- LD A,(B_WR5) ;;; GET MEMORY COPY
- LD B,A ;;; SAVE ORIGINAL FOR A MOMENT...
- AND BLED ;;; CHECK THE CON LED BIT
- LD A,B ;;; RETREIVE ORIGINAL
- JP Z,CON_F0 ;;; BIT IS A 0, SO LED IS ON, MAKE OFF
- ;ELSE MAKE IT GO ON (BECAUSE IT IS NOW OFF)
- AND 0FFH-BLED ;;; SET DTR BIT TO 0 SO LED GOES ON
- JP CON_F1
- CON_F0:
- OR BLED ;;; SET DTR BIT TO 1 SO LED GOES OFF
- CON_F1:
- OUT (B_CTL),A ;;; ACTUALLY TURN OFF CON LED NOW...
- LD (B_WR5),A ;;; UPDATE MEMORY COPY
- POP BC
- POP AF
- RET
- ;
- ; IF CATASTROPHIC ERROR OCCURS RESET - IF RUNNING WITH BPQ
- ; SWITCH CODE, WE CANT REALLY AFFORT TO HANG UP
- ;
-
- RESTART:
- DI
- LD HL,0
- RSLOOP:
- DEC HL
- LD A,H
- OR L
- JR NZ,RSLOOP ; DELAY A BIT
-
- JP 0 ; START AGAIN
-
- COND PROM
-
- DEFS START+8000H-$
-
- ENDC
-
- FREE_RAM DEFS 0
-
-
- ;-----------------------------------------------------------------------------
- ; THESE ARE THE TX REAL-TIME ROUTINE DATA STRUCTURES. THEY ARE USED FOR
- ; TIMING REQUIRED WITH TX CONTROL. THERE ARE 3 ACTIONS THAT MUST BE TIMED:
- ; 1) TXR_DELAY TX DELAY TIMER (FOR TXDELAY FUNCTION)
- ; 2) TXR_SLOTTIME PART OF P-PERSISTENCE BACKOFF
- ; 3) TXR_TAIL TIMER TO BE SENDING SYNCS BEFORE DROPPING RTS
-
- ; THE DATA STRUCTURE CAN BE THOUGHT OF LOGICALLY AS THIS:
- ;
- ; +------------------------+
- ; | ROUTINE ENABLED (BYTE) | IS 0 IF NOT ENABLED, NON ZERO IF ENABLED
- ; +------------------------+--------------------------------------+
- ; | POINTER TO ROUTINE TO EXECUTE WHEN TIMER EXPIRES (WORD) |
- ; +---------------------------------------------------------------+
- ; | 16-BIT DOWNCOUNTER TIMER VALUE, IN 10S OF MILLISECONDS (WORD) |
- ; +---------------------------------------------------------------+
- ;
- ; THE DATA STRUCTURE HAS ONE ENTRY FOR EACH OF THE 3 TIMER EVENTS. PHYSICALLY
- ; IT IS ORGANIZED AS 3 SEPARATE LISTS, ONE FOR EACH OF THE ENABLES, ONE FOR
- ; EACH OF THE ROUTINE POINTERS, AND ONE FOR EACH OF THE TIMER VALUES.
- ;
- ; AN INTERUPT ROUTINE, RUNNING AT 10 MILLISECOND TICKS, DECREMENTS THE VALUES
- ; IN EACH OF THE DOWNCOUNT TIMER WHETHER A ROUTINE IS ENABLED OR NOT. WHEN
- ; DOWNCOUNT VALUE GOES TO 0 (OR NEGATIVE) THEN THE ROUTINE "FIRES". THIS
- ; CHECKING FOR "FIRING" HAPPENS AT NON-INTERRUPT LEVEL IN THE COMMUTATOR LOOP.
- ; WITH THIS SCHEME, THE MINIMUM TIME BEFORE FIRING IS 10 MILLISECONDS, AND THE
- ; MAXIMUM TIME IS 327.67 SECONDS (OVER 5 MINUTES). FOR EXAMPLE, FOR A
- ; TXDELAY OF 600 MILLISECONDS, THE TIMER WOULD GET LOADED WITH DECIMAL 60.
- ;
- ; WHEN A ROUTINE FIRES, IT GETS MARKED AS "DISABLED", SO YOU'D NEED TO
- ; EXPLICITLY RE-ENABLE IT IF THIS IS REQUIRED
-
- ; NOTE TOO THAT A CLOCK COULD BE EASILY IMPLEMENTED. IF WE INSERTED ANOTHER
- ; EVENT INTO OUR LIST WITH A TIMEOUT OF 100, THEN EVERY SECOND A ROUTINE WOULD
- ; BE CALLED. IN THAT ROUTINE, WE COULD INCREMENT THE SECONDS FIELD (AND
- ; POSSIBLY MINUTES, HOURS, DAYS, YEARS FIELDS) OF A TIME-OF-DAY CLOCK. WE
- ; WOULD IMMEDIATELY RE-ACTIVATE THIS TIMER TO GET THE NEXT TICK, ETC.
-
-
- TXQ_ENABLES DEFS 4 ; 4 BYTES FOR THE ENABLES
-
- TXQ_ADDRESSES DEFS 8 ; 4 WORDS FOR THE ROUTINE POINTERS
-
- TXQ_TIMERS DEFS 8 ; 4 WORDS FOR THE ROUTINE TIMERS
-
- ; NOTE THE LAST SLOT IN THIS TABLE IS FOR R_TEST ROUTINE, WHICH BLINKS STA LED
- ; IT IS NOT USED NORMALLY, JUST FOR HELPING ME DEBUG THIS!
-
- ; SOME EQUATES TO SAVE US FROM DOING CONTORTED THINGS WHEN WE WANT TO CHECK IF
- ; A ROUTINE IS ENABLED IN PLACES OTHER THAN THE COMMUTATOR LOOP, OR FOR
- ; ENABLING ROUTINES, ETC.
-
- TXQE_DELAY EQU TXQ_ENABLES+0
- TXQE_SLOTTIME EQU TXQ_ENABLES+1
- TXQE_TAIL EQU TXQ_ENABLES+2
- TXQE_CWID EQU TXQ_ENABLES+3
-
- ; SAME IDEA, BUT FOR THE TIMER VALUES
-
- TXQT_DELAY EQU TXQ_TIMERS+0
- TXQT_SLOTTIME EQU TXQ_TIMERS+2
- TXQT_TAIL EQU TXQ_TIMERS+4
- TXQT_CWID EQU TXQ_TIMERS+6
-
- ; WE DON'T DO THIS FOR THE ROUTINE ADDRESSES, SINCE THEY DON'T CHANGE ONCE
- ; THEY ARE INITIALIZED.
-
-
- TXDELAY DEFS 1 ; TRANSMITTER DELAY TIME VALUE
-
- PERSISTENCE DEFS 1 ; PERSISTENCE VALUE
-
- SLOTTIME DEFS 1 ; SLOT TIME VALUE
-
- TAILTIME DEFS 1 ; TX TAIL TIME VALUE
-
-
- NBUFFERS DEFS 1 ; UP TO 255 BUFFERS
-
- FREE DEFS 2 ; ADDRESS OF 1ST BUFFER ON FREE LIST
-
-
- RX_BUF DEFS 2 ; ADDRESS OF CURRENT RECEIVE BUFFER
-
- RX_HEAD DEFS 2 ; ADDRESS OF 1ST RX BUFFER
-
- RX_ALLOCATED_BUFFER DEFS 1 ; SET NON-ZERO IF WE'RE IN RX STATE
-
- RX_FLUSHING DEFS 1 ; IS NON-0 IF WE RAN OUT OF BUFFER
- ; SPACE AND ARE CURRENTLY FLUSHING THIS
- ; FRAME BEING RECEIVED. USED BY
- ; IA_RCA AND RESET BY IA_EXT.
-
-
- IN_BUFFER DEFS 2 ; ADDR OF CURRENT INPUT BUFFER
-
- IN_HEAD DEFS 2 ; ADDR OF 1ST INPUT BUFFER
-
- IN_ALLOCATED_BUFFER DEFS 1 ; IS NOT 0 IF WE'VE ALREADY ALLOC'D BUF
-
- IN_STATE DEFS 1 ; 1 ; INPUT STATE MACHINE STATE
- ; ASSUME THAT WE'VE SEEN AN FEND FROM
- ; (NON-EXISTENT) "PREVIOUS" FRAME. THIS
- ; MEANS THAT WHEN WE ARE RECEIVING DATA
- ; FROM USER, THERE NEED BE ONLY THE
- ; FEND CHAR AT THE END OF A FRAME, AND
- ; NOT AT THE BEGINNING (ALTHOUGH IF A
- ; FEND IS AT THE BEGINNING, IT IS
- ; IGNORED.)
-
- OUT_STARTED DEFS 1 ; OUTPUT NOT STARTED YET (LOGICAL VAR)
-
- OUT_HEAD_CBUF DEFS 2 ; OUT_TOP ; ADDRESS OF BUFFER TO BE OUTPUT RS232
-
- OUT_TAIL_CBUF DEFS 2 ; OUT_TOP ; POINTER TO NEXT FREE OUTPUT BUFFER
-
- OUT_CHAIN_HEAD DEFS 2 ; ADDR OF BUFFER WE ARE NOW OUTPUTTING
-
-
- TX_STARTED DEFS 1 ; NON-ZERO IF WE'VE BEGUN TXING CHARS
-
- TX_HEAD_CBUF DEFS 2 ; TX_TOP ; CURRENT ACTIVE CBUF ENTRY (IF ACTIVE)
-
- TX_TAIL_CBUF DEFS 2 ; TX_TOP ; NEXT FREE CBUF ENTRY
-
-
- TX_CHAIN_HEAD DEFS 2 ; HOLDS ADDRESS OF THE CURRENT BUFFER
- ; CHAIN HEAD THAT WE ARE TRANSMITTING
-
- TX_OUTSTANDING DEFS 1 ; NUMBER OF TX CBUFS QUEUED UP FOR TX
-
-
- DCD_STATE DEFS 1 ; IS NON 0 IF DCD LED IS ON
-
-
- ;THESE NEXT TWO ARE USED BY THE IB_TBE INTERRUPT ROUTINE.
-
- IB_ESC_MODE DEFS 1 ; NOT IN ESCAPED MODE
-
- IB_CHAR DEFS 1 ; NEXT CHAR TO SEND IF ESCAPED MODE
-
- IN_BREAK DEFS 1 ; NON-ZERO IF WE ARE IN A BREAK DETECT
- ; ON THE ASYNC PORT
-
- FULL_DUPLEX DEFS 1 ; NOT INITIALLY FULL DUPLEX
-
- A_WR5 DEFS 1 ; ALEDOFF ; STATE OF STA LED & RTS (PTT) LINE,
- ; MAINLY... (FOR CH A ONLY [MODEM] )
-
- B_WR5 DEFS 1 ; BLEDOFF
- DEFS 1 ; WHY??
-
- MINUTES DEFS 1 ; FOR CWID TIMING
- CWIDFLAG DEFS 1 ; ID OUTSTANDING FLAG
- CWIDPTR DEFS 2 ; NEXT CWID BIT TO SEND
- LASTBIT DEFS 1 ; CURRENT CWID STATE
-
- OUT_TOP DEFS 2*255 ; "TOP" OF OUTPUT CIRCULAR BUFFER
- ; 255 OUT BUFFER CHAINS PENDING, MAX
- OUT_BOTTOM DEFS 2 ; "BOTTOM" OF OUTPUT CIRCULAR BUFFER
-
- TX_TOP DEFS 255*2
- TX_BOTTOM DEFS 2
-
-
- BOTTOM DEFS 0 ; END OF ALL CODE & PREDEFINED DATA
-
-
- ; NOTES ON NOMENCLATURE:
-
- ; OUT = TO TTY PORT; IN = FROM TTY PORT
- ; TX = TO MODEM; RX = FROM MODEM
- ;
- ; ;;; MEANS THAT THAT CODE EXECUTES WITHOUT INTERRUPTS ENABLED (EXCEPT
- ; FOR THE INITIALIZATION CODE)
- ;
- ;
- ; I HAVE BEEN CAREFUL WITH JR/JP USE. I USE JP WHEN THE JUMP IS LIKELY AND
- ; WHERE SPEED IS IMPORTANT. I USE JR WHEN THE JUMP IS UNLIKELY SO THAT I CAN
- ; SAVE A FEW CYCLES. JP ALWAYS USES 10 CYCLES WHETHER IT JUMPS OR NOT, BUT
- ; JR USES EITHER 7 OR 12 T STATES, NO JUMP/JUMP, RESPECTIVELY.
-
-
- ; BUFFERS KEPT HERE AT END.
-
- END START
-
-
-